Scrapy爬虫工程设计

最近做了一些爬虫的工作,并涉及到了工程的部署和自动化,借此机会整理一下,工程结构如图:

 

image.png

工程主要包含4个部分:

  • 获取有效代理ip
  • 数据管理
  • 不同任务的spider
  • spider在线调度和管理

1.获取有效代理ip

代理IP可从国内的几个网站爬取,如西刺。可以肯定免费的代理IP大部分都是不能用的,不然别人为什么还提供付费的(不过事实是很多代理商的付费IP也不稳定,也有很多是不能用)。所以采集回来的代理IP不能直接使用,需要写一个过滤程序去用这些代理访问目标网站,看是否可以正常使用。我的项目里所有爬虫任务都是每日定时开启的,所以爬取和过滤的过程被设计在了一个spider中,主任务开启的前三个小时执行 ,因为检测代理是个很慢的过程。

以西刺网站为例,创建任务spider:

 

class Proxy(Spider):
    name = "scrapy_proxy"
    #设置custom_settings,执行爬取代理ip的任务时不使用代理 
    custom_settings = {
        'DOWNLOADER_MIDDLEWARES' : {
            'scrapy.contrib.downloadermiddleware.httpproxy.HttpProxyMiddleware': 543,
        }
    }
    base_url = "http://www.xicidaili.com/nn/"


    def __init__(self, *a , **kw):
        super(Proxy, self).__init__(*a, **kw)
        self.sql = SqlHelper()#数据管理方法
        self.create_proxyurl_table()#创建存储有效代理ip的table

    def create_proxyurl_table(self):
        command = (
            "CREATE TABLE IF NOT EXISTS {} ("
            "`id` INT(8) NOT NULL AUTO_INCREMENT,"
            "`url` TEXT(20) NOT NULL ,"
            "`create_time` DATETIME NOT NULL,"
            "PRIMARY KEY(id)"
            ") ENGINE=InnoDB".format(config.proxy_url_table)
        )
        self.sql.create_table(command)

爬取前10页的IP:

 

    def start_requests(self):
        for i in range(1,10):
            url = self.base_url + str(i)
            yield Request(
                url = url,
                headers = {
                        'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8',
                        'Accept-Encoding': 'gzip, deflate, sdch',
                        'Accept-Language': 'zh-CN,zh;q=0.8,en;q=0.6',
                        'Connection': 'keep-alive',
                        'Host': 'www.xicidaili.com',
                        'Upgrade-Insecure-Requests': '1',
                        'User-Agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10.11; rv:51.0) Gecko/20100101 Firefox/51.0',
                },
                callback = self.parse_all,
                errback = self.error_parse
            )

解析内容,验证IP有效性,并存储

 

    def parse_all(self,response):
        proxys = response.xpath("//table[@id='ip_list']/tr").extract()
        for i ,proxy in enumerate(proxys):
            if i==0 :continue
            sel = Selector(text = proxy)
            ip = sel.xpath("//td[2]/text()").extract_first()
            port = sel.xpath("//td[3]/text()").extract_first()
            speed = sel.xpath("//td[7]/div[@class='bar']/@title").extract_first().replace('秒','')
            connect = sel.xpath("//td[8]/div[@class='bar']/@title").extract_first().replace('秒','')

            proxy = str(ip) + ':'+str(port)
            self.validateIP(proxy)


    def validateIP(self,proxy):
        try:
            requests.post('目标网站地址',proxies={"http":proxy},timeout=10)
        except:
            util.log(proxy + '  connect failed')
        else:
            util.log("grab ip :%s" % (proxy))
            dt = datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S")
            msg = (None,proxy,dt)
            command = ("INSERT IGNORE INTO {}"
                    "(id,url,create_time)"
                    "VALUES(%s,%s,%s)".format(config.proxy_url_table)
            )
            self.sql.insert_data(command, msg)

2.数据存储

创建一个工具类,包含常用的建表,查询,插值等操作

 

#-*- coding: utf-8 -*-

import logging
import mysql.connector
import utils
import config

from singleton import Singleton


class SqlHelper(Singleton):
    def __init__(self):
        self.database_name = config.development_database_name
        self.init()

    def init(self):
        self.database = mysql.connector.connect(**config.development_database_config)
        self.cursor = self.database.cursor()

        self.create_database()
        self.database.database = self.database_name

    def create_database(self):
        try:
            command = 'CREATE DATABASE IF NOT EXISTS %s DEFAULT CHARACTER SET \'utf8\' ' % self.database_name
            utils.log('sql helper create_database command:%s' % command)
            self.cursor.execute(command)
        except Exception, e:
            utils.log('SqlHelper create_database exception:%s' % str(e), logging.WARNING)

    def create_table(self, command):
        try:
            utils.log('sql helper create_table command:%s' % command)
            self.cursor.execute(command)
            self.database.commit()
        except Exception, e:
            utils.log('sql helper create_table exception:%s' % str(e), logging.WARNING)

    def insert_data(self, command, data):
        try:
            #utils.log('insert_data command:%s, data:%s' % (command, data))

            self.cursor.execute(command, data)
            self.database.commit()
        except Exception, e:
            utils.log('sql helper insert_data exception msg:%s' % str(e), logging.WARNING)

    def execute(self, command):
        try:
            utils.log('sql helper execute command:%s' % command)
            data = self.cursor.execute(command)
            self.database.commit()
            return data
        except Exception, e:
            utils.log('sql helper execute exception msg:%s' % str(e))
            return None

    def query(self, command):
        try:
            #utils.log('sql helper execute command:%s' % command)

            self.cursor.execute(command)
            data = self.cursor.fetchall()

            return data
        except Exception, e:
            utils.log('sql helper execute exception msg:%s' % str(e))
            return None

    def query_one(self, command):
        try:
            utils.log('sql helper execute command:%s' % command)

            self.cursor.execute(command)
            data = self.cursor.fetchone()

            return data
        except Exception, e:
            utils.log('sql helper execute exception msg:%s' % str(e))
            return None

3. Spiders

关于Scrapy相关的基础知识,请查阅Python系列文章

4.Spider在线调度和管理

SpiderKeeper是一个scrapy的管理后台,基于Scrapyd和Flask。界面如下:

 

image.png

 

主要功能包括:

  • Job Dashboard
  • Periodic Jobs
  • Deploy
  • Running Stats
  • Manage



作者:SamDing
链接:https://www.jianshu.com/p/b360f53930e7
来源:简书
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

### 回答1: Python爬虫Scrapy是一种用于爬取网站数据的工具。它可以自动化地从网站上获取数据,并将其存储在本地或远程服务器上。Scrapy使用Python编写,具有高效、灵活和可扩展的特点,可以处理大量数据和复杂的网站结构。使用Scrapy可以快速地获取所需的数据,从而为数据分析和挖掘提供支持。 ### 回答2: Python爬虫是一种快速、高效的网络爬虫工具,它利用Python语言及其强大的第三方库实现自动化爬取互联网信息的过程。而Scrapy是一个Python爬虫框架,可以帮助我们快速构建持续性的爬虫应用程序。 基于Scrapy框架的爬虫程序设计,首先需要明确自己的目标:确定目标网站、确定目标页面、确定目标信息。其次,在编写程序之前,我们需要构建好爬虫的数据模型,包括目标页面的结构、目标信息的抽取规则等。Scrapy框架的核心就是Spider,将会快速地处理目标页面,解析数据并且提取出所需信息。这些信息可以经过清洗、存储和分析等处理过程,最终达到我们的预期需求。 爬虫程序的主要步骤是: 1.创建一个Scrapy项目,包括spider、items、pipelines等。 2.定义spider,包括start_urls、parse等。 3.定义item,表示解析结果的结构。 4.定义pipeline,用于处理抓取到的数据。 5.运行爬虫程序并保存数据。 在使用Scrapy进行网络爬虫时,需要遵守相关法律法规,尊重目标网站的利益和知识产权,不进行违法、违规的操作,同时遵守robots.txt协议等规定,如不得爬取不允许抓取的页面。 总之,对于想要进行网络数据采集的人来说,Scrapy是一个非常强大的Python爬虫框架。它支持异步IO和协程等功能,可以快速、高效地提取目标数据。但是,使用Scrapy时需要遵循规则,合理利用,不进行违法、违规操作。 ### 回答3: Scrapy是基于Python语言的爬虫框架,它可以更好的帮我们实现爬取网站的任务。scrapy提供了一整套爬虫流程和一些基本机制,比如:异步处理,中间件机制,数据管道,数据解析等等。这些机制可以帮我们更加简便和高效地进行网络爬取任务。 使用Scrapy爬取网站有以下几个步骤: 1. 安装Scrapy框架 我们需要提前安装好Python和Scrapy框架。安装Scrapy比较方便,可以通过pip来安装,命令为:pip install scrapy。 2. 创建scrapy爬虫工程 我们需要使用scrapy startproject 项目名的命令来创建项目,并进入到项目的工程目录来创建爬虫内容,命令为:scrapy genspider 爬虫名 域名。 3. 配置scrapy爬虫的设置 进入到Scrapy工程目录,找到settings.py文件,修改里面的文件配置,包括:User-Agent,爬虫间隔时间,ip代理池设置等等。 4. 配置scrapy爬虫的项 在Spider中定义需要爬取的网站信息,包括URL地址和需要获取的数据。 5. 实现URL地址的解析 在Spider中写解析函数,对爬虫获取到的URL进行解析,获取需要的数据内容。 6. 爬虫启动 最后,使用命令scrapy crawl 爬虫名,启动爬虫。爬取的URL资源会被输出进行。如果爬虫爬取的URL过多,那么可以使用命令scrapy crawl 爬虫名 -o 文件名.格式名来保存爬虫获取到的数据内容。 总的来说,Scrapy是一个快速高效的爬虫框架,有着多种策略来处理不同种类的爬虫需求。使用Scrapy进行爬虫的开发,不仅能够为我们省去很多重复性工作,还能够提高我们的开发效率和爬虫的运行效率。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值