Advertisement

爬虫技术-Scrapy框架介绍

阅读量:

Scrapy采集框架

1 学习目标

1、框架流程和结构设计原理

2、框架爬虫程序编写

3、框架日志模块使用

4、框架请求发送流程

2 scrapy简介

Scrapy是一个基于纯Python语言开发的解析网页结构并提取关键信息的应用框架,在各个领域中都有广泛的应用价值。普通用户只需自定义几个核心功能模块即可便捷地构建起高效的数据采集系统。该工具能够快速有效地获取网页信息以及各类图像资料。

2.0 单个爬虫编写

复制代码
 class Spider(object):

    
     def __init__(self):
    
     # 负责全局配置
    
     pass
    
  
    
     def url_list(self):
    
     # 负责任务池维护
    
     pass
    
  
    
     def request(self):
    
     # 负责网络请求模块
    
     pass
    
  
    
     def parse(self):
    
     # 负责解析数据模块
    
     pass
    
  
    
     def save(self):
    
     # 负责数据存储
    
     pass
    
  
    
     def run(self):
    
     # 负责模块调度
    
     pass
    
    
    
    
    代码解读

2.1 架构介绍

2.2.1 名词解析
2.2.2 运行逻辑图

3 框架使用

3.1 项目搭建

3.1.1 框架安装

查找历史版本:https://pypi.org/project/Scrapy/#history

复制代码
    pip install scrapy==2.3.0
    
    代码解读
3.1.2 项目创建
复制代码
    scrapy startproject xxxx
    
    代码解读

文件介绍

复制代码
 - scrapy.cfg:它是 Scrapy 项目的配置文件,其内定义了项目的配置文件路径、部署相关信息等内容。

    
 - items.py:它定义 Item 数据结构,所有的 Item 的定义都可以放这里。
    
 - pipelines.py:它定义 Item Pipeline 的实现,所有的 Item Pipeline 的实现都可以放这里。
    
 - settings.py:它定义项目的全局配置。
    
 - middlewares.py:它定义 Spider Middlewares 和 Downloader Middlewares 的实现。
    
 - spiders:其内包含一个个 Spider 的实现,每个 Spider 都有一个文件。
    
    
    
    
    代码解读
3.1.3 创建爬虫

Spider 是一个自定义的类,
通过它来进行网页内容抓取和结果解析。
不过这个类必须继承 Scrapy 提供的 scrapy.Spider 类,
并指定名称和启动请求,
同时还需要定义如何处理爬取结果的方法。

复制代码
 cd 项目路径

    
 scrapy genspider  爬虫名称  目标地址
    
    
    
    
    代码解读

配置文件简介

复制代码
 # Scrapy settings for ScrapyDemo project

    
  
    
 # 自动生成的配置,无需关注,不用修改
    
 BOT_NAME = 'ScrapyDemo'
    
 SPIDER_MODULES = ['ScrapyDemo.spiders']
    
 NEWSPIDER_MODULE = 'ScrapyDemo.spiders'
    
  
    
 # 设置UA,但不常用,一般都是在MiddleWare中添加
    
 USER_AGENT = 'ScrapyDemo (+http://www.yourdomain.com)'
    
  
    
 # 遵循robots.txt中的爬虫规则,很多人喜欢False,当然我也喜欢....
    
 ROBOTSTXT_OBEY = True
    
  
    
 # 对网站并发请求总数,默认16
    
 CONCURRENT_REQUESTS = 32
    
  
    
 # 相同网站两个请求之间的间隔时间,默认是0s。相当于time.sleep()
    
 DOWNLOAD_DELAY = 3
    
 # 下面两个配置二选一,但其值不能大于CONCURRENT_REQUESTS,默认启用PER_DOMAIN
    
 # 对网站每个域名的最大并发请求,默认8
    
 CONCURRENT_REQUESTS_PER_DOMAIN = 16
    
 # 默认0,对网站每个IP的最大并发请求,会覆盖上面PER_DOMAIN配置,
    
 # 同时DOWNLOAD_DELAY也成了相同IP两个请求间的间隔了
    
 CONCURRENT_REQUESTS_PER_IP = 16
    
  
    
 # 禁用cookie,默认是True,启用
    
 COOKIES_ENABLED = False
    
  
    
 # 请求头设置,这里基本上不用
    
 DEFAULT_REQUEST_HEADERS = {
    
 #   'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8',
    
 #   'Accept-Language': 'en',
    
 }
    
  
    
 # 配置启用Spider MiddleWares,Key是class,Value是优先级
    
 SPIDER_MIDDLEWARES = {
    
     'ScrapyDemo.middlewares.ScrapydemoSpiderMiddleware': 543,
    
 }
    
  
    
 # 配置启用Downloader MiddleWares
    
  
    
 DOWNLOADER_MIDDLEWARES = {
    
     'ScrapyDemo.middlewares.ScrapydemoDownloaderMiddleware': 543,
    
 }
    
  
    
 # 配置并启用扩展,主要是一些状态监控
    
 EXTENSIONS = {
    
     'scrapy.extensions.telnet.TelnetConsole': None,
    
 }
    
  
    
 # 配置启用Pipeline用来持久化数据
    
 ITEM_PIPELINES = {
    
    'ScrapyDemo.pipelines.ScrapydemoPipeline': 300,
    
 }
    
    
    
    
    代码解读

3.2 执行爬虫

3.2.1 终端运行爬虫
  • 需要去到项目跟路径执行指令
复制代码
    scrapy crawl xxxx
    
    代码解读
3.2.2 脚本运行
  • 在Scrapy中包含名为cmdline的模块负责管理终端命令。导入该模块后即可实现终端操作。
  • Scrapy中的execute函数用于执行与终端相关的操作。
复制代码
 from scrapy import cmdline

    
  
    
 cmdline.execute("scrapy crawl xxxx".split())
    
 cmdline.execute(["scrapy","crawl","xxxx"])
    
    
    
    
    代码解读

运行报错

复制代码
    ImportError: cannot import name 'HTTPClientFactory' from 'twisted.web.client' (unknown location)
    
    代码解读

解决:

复制代码
 # 降低Twisted版本

    
 pip install Twisted==20.3.0
    
    
    
    
    代码解读

3.3 scrapy shell调试

基本使用

复制代码
    scrapy shell https://dig.chouti.com/
    
    代码解读

数据提取

复制代码
 datas =res.xpath('//div[@class="link-con"]/div')

    
 for i in datas:
    
    print(i.xpath('.//a[@class="link-title link-statistics"]/text()').extract_first())
    
    
    
    
    代码解读

4 实战演示

4.1 spider结构

复制代码
 import scrapy

    
 from scrapy import cmdline
    
 import bs4
    
  
    
 class TopSpider(scrapy.Spider):
    
     name = 'top'
    
     # allowed_domains = ['top.com']
    
     start_urls = ['https://book.douban.com/top250?start=0']
    
  
    
     def parse(self, response):
    
     #print(response.text)
    
     bs = bs4.BeautifulSoup(response.text, 'html.parser')
    
     datas = bs.find_all('tr', class_="item")
    
     for data in datas:
    
         item = {}
    
         item['title'] = data.find_all('a')[1]['title']
    
         item['publish'] = data.find('p', class_='pl').text
    
         item['score'] = data.find('span', class_='rating_nums').text
    
         print(item)
    
         
    
 if __name__ == '__main__':
    
     cmdline.execute('scrapy crawl top'.split())
    
    
    
    
    代码解读

4.2 定义数据

scrapy中,我们会专门定义一个用于记录数据的类

复制代码
 import scrapy

    
  
    
 class DoubanItem(scrapy.Item):
    
     # define the fields for your item here like:
    
     # name = scrapy.Field()
    
     title = scrapy.Field()
    
     #定义书名的数据属性
    
     publish = scrapy.Field()
    
     #定义出版信息的数据属性
    
     score = scrapy.Field()
    
    
    
    
    代码解读

scrapy.Field()这一行代码的功能是使得数据能够按照类似于字典的格式存储。然而存储的方式并不是传统的字典而是我们自定义的一个DoubanItem对象类型。

4.3 定义管道存储

4.3.1 配置管道

放开配置文件

复制代码
 ITEM_PIPELINES = {

    
    'douban.pipelines.DoubanPipeline': 300,
    
 }
    
    
    
    
    代码解读
4.3.2 存储文件编写
复制代码
 import json

    
  
    
 class DoubanPipeline:
    
     def process_item(self, item, spider):
    
     with open('da.json', 'a+', encoding='utf-8') as f:
    
         f.write(json.dumps(dict(item), ensure_ascii=False))
    
         f.write('\r\n')
    
    
    
    
    代码解读
4.3.3 配置日志

配置日志来做记录

复制代码
 LOG_LEVEL = 'WARNING'

    
 LOG_FILE = './log.log'
    
    
    
    
    代码解读

配置日志为警告级别,如果有数据是警告级别那么将记录到文件

5 scrapy表单处理

5.1 目标地址
5.2 程序编写
复制代码
 import scrapy

    
  
    
 class PostTestSpider(scrapy.Spider):
    
     name = 'post_test'
    
     allowed_domains = ['cninfo.com']
    
     # start_urls = ['http://www.cninfo.com.cn/new/disclosure']
    
  
    
     def start_requests(self):
    
     url = 'http://www.cninfo.com.cn/new/disclosure'
    
     for i in range(1,5):
    
         form_data = {
    
             "column": "szse_gem_latest",
    
             "pageNum": str(i),
    
             "pageSize": "30",
    
             "sortName": "",
    
             "sortType": "",
    
             "clusterFlag": "true"
    
         }
    
  
    
         yield scrapy.FormRequest(url=url,formdata=form_data,meta={'page':form_data['pageNum']})
    
  
    
     def parse(self, response):
    
     print(f'正在采集第{response.meta.get("page")}页')
    
    
    
    
    代码解读

6 框架扩展

6.1 框架去重设计

dont_filter实现了框架去重的功能

复制代码
 import scrapy

    
 import json
    
  
    
 from scrapy import cmdline
    
  
    
  
    
 class HuyaSpider(scrapy.Spider):
    
     name = 'huya'
    
     # allowed_domains = ['hy.com']
    
  
    
     def start_requests(self):
    
     url = ['https://www.huya.com/cache.php?m=LiveList&do=getLiveListByPage&gameId=1663&tagAll=0&page=2',
    
            'https://www.huya.com/cache.php?m=LiveList&do=getLiveListByPage&gameId=1663&tagAll=0&page=2']
    
     for i in url:
    
         # 框架默认对地址进行了去重
    
         yield scrapy.Request(url=i,dont_filter=False)
    
  
    
  
    
     def parse(self, response):
    
     items = json.loads(response.text)
    
     data = items.get('data').get('datas')
    
     print(len(data))
    
  
    
 if __name__ == '__main__':
    
     cmdline.execute('scrapy crawl huya'.split())
    
    
    
    
    代码解读

7 各目录文件详解

(1)爬虫文件

spiders 下的 jingding.py 是 scrapy 自动为我们生成的爬虫文件。

该框架中的scrapy.Spider类是最基础的,并且任何编写好的爬虫都必须继承此类以实现基本功能。 该框架中常用的属性和方法如下:

name:定义spider名字的字符串。

allowed_domains:包含了spider允许爬取的域名(domain)的列表,可选。

start_urls:构成初始 URL 的元组或列表。当未指定特定 URL 时,scrapy 爬虫将从该列表中启动爬取过程。

start_requests函数(self):通过调用make_requests_from url()方法创建Requests实例,并将此实例传递给Scrapy进行请求处理后返回响应结果。此方法必定返回一个可迭代的对象(如列表或集合),其中包含spider用于抓取网页所需的第一条Request(此功能通常基于start_urls参数配置)。特别地,在spider启动抓取操作而未指定start_urls参数时,默认情况下会触发此方法以执行抓取任务。

每当解析某个URL响应时

Request 对象的用法:

复制代码
    yield Request(url[, callback, method='GET', headers, body, cookies, meta, encoding='utf-8', priority=0, dont_filter=False, errback, flags])

    
    代码解读

url:请求的 url;

callback:作为响应处理请求后的返回数据的关键功能组件,在编程环境中通常与JavaScript中的 promise语法结合使用;当未指定回调时,默认将调用JavaScript内置的parse方法获取响应内容。

meta:表示用户自定义向回调函数传递的一个特定参数,在实际应用中这一参数通常也被用来进行跨站脚本防护(SSTF)操作。需要注意的是,在很多框架或框架组件之间开发时,默认的做法是将此参数用于Middleware组件的处理逻辑。

meta = {‘name’ : ‘Zarten’}
回调函数中获取:my_name = response.meta[‘name’]

method:采用HTTP方式,默认采用GET方法,并非必须指定。在需要发送POST请求的情况下,请使用FormRequest来处理。

method:采用HTTP方式,默认采用GET方法,并非必须指定。在需要发送POST请求的情况下,请使用FormRequest来处理。

HTTP头部信息:通常可以在settings或middlewares中进行配置;此外,在middlewares中也可以进行相应的配置。

body字段的类型为字符串类型,属于请求体的一部分,在大多数情况下不需要设置(通常情况下不需要设置)。可以通过body字段来接收GET和POST请求的数据

cookies:dict或list类型,请求的cookie

实例:

复制代码
 import scrapy

    
  
    
  
    
 class HuyaSpider(scrapy.Spider):
    
     name = 'huya'
    
     # allowed_domains = ['huya.com']
    
     # start_urls = ['http://huya.com/']
    
  
    
     def start_requests(self):
    
     url = ['https://www.huya.com/cache.php?m=LiveList&do=getLiveListByPage&gameId=1663&tagAll=0&page=1',
    
            'https://www.huya.com/cache.php?m=LiveList&do=getLiveListByPage&gameId=1663&tagAll=0&page=1']
    
     for i in url:
    
         # 框架默认对地址进行了去重
    
         yield scrapy.Request(url=i,dont_filter=False)
    
  
    
     def parse(self, response):
    
     print(response)
    
  
    
 # <200 https://www.huya.com/cache.php?m=LiveList&do=getLiveListByPage&gameId=1663&tagAll=0&page=1>
    
    
    
    
    代码解读

(2)middlewares.py

middlewares.py 制定Spider_middlewares_and_downloader_middlewares的具体实施细节

1) Spider Middlewares

Spider 中间件是一种嵌入在 Scrapy 网页处理流程中的钩子架构。您可以通过编写代码来处理 Spiders 发送的 response 以及其生成的 item 和 request。若要启用 Spider 中间件(Spider Middlewares),则需在设置文件 setting.py 中对 SPIDER_MIDDLEWARES 字典进行配置。其中键指定中间件的位置路径,值决定了中间件执行时的优先级(order)。

复制代码
 SPIDER_MIDDLEWARES = {

    
     'myproject.middlewares.CustomSpiderMiddleware': 543, 
    
     }
    
    
    
    
    代码解读

SPIDER_MIDDLEWARES 设置会与Scrapy定义的 SPIDER_MIDDLEWARES_BASE 设置合并(但不是覆盖),而后根据顺序(order)进行排序,最后得到启用中间件的有序列表: 第一个中间件是最靠近引擎的,最后一个中间件是最靠近spider的。
关于如何分配中间件的顺序请查看 SPIDER_MIDDLEWARES_BASE 设置,而后根据您想要放置中间件的位置选择一个值。由于每个中间件执行不同的动作,您的中间件可能会依赖于之前(或者之后)执行的中间件,因此顺序是很重要的。
如果您想禁止内置的(在 SPIDER_MIDDLEWARES_BASE 中设置并默认启用的)中间件, 您必须在项目的 SPIDER_MIDDLEWARES 设置中定义该中间件,并将其值赋为 None 。 例如,如果您想要关闭off-site中间件:

复制代码
 SPIDER_MIDDLEWARES = {

    
     'myproject.middlewares.CustomSpiderMiddleware': 543,
    
     'scrapy.contrib.spidermiddleware.offsite.OffsiteMiddleware': None, }
    
    
    
    
    代码解读

Spider 中间件方法:

复制代码
 process_spider_input(response, spider)

    
 # response (Response 对象) – 被处理的response 
    
 # spider (Spider 对象) – 该response对应的spider
    
    
    
    
    代码解读

每当 response 通过 spider middleware 处理时,
此方法将被激活以处理此 response。
若此函数返回 None,
则 Scrapy 继续执行其他中间件直至 spider 处理此 response;
若此函数抛出异常,
则 Scrapy 将停止其他中间件并触发 request 的 errback 处理。
errback 的输出结果将作为新的输入重新注入到中间件链中,
并使用 process_spider_output() 方法进行后续处理。
当 errback 抛出异常时,
它将传递给 process_spider_exception() 方法进行处理。

复制代码
 process_spider_output(response, result, spider)

    
 # response (Response 对象) – 生成该输出的response 
    
 # result (包含 Request 或 Item 对象的可迭代对象(iterable)) – spider返回的result 
    
 # spider (Spider 对象) – 其结果被处理的spider
    
    
    
    
    代码解读

当Spider处理响应并返回结果时,该方法将被调用. process_spider_output()必须返回一个包含Request或Item对象的可迭代对象(iterable).

复制代码
 process_spider_exception(response, exception, spider)

    
 # response (Response 对象) – 异常被抛出时被处理的response 
    
 # exception (Exception 对象) – 被跑出的异常 
    
 # spider (Spider 对象) – 抛出该异常的spider
    
    
    
    
    代码解读

在 spider 或其他相关中间件引发 process_spider_input 异常的情况下, 该方法会被触发. 此过程会要求 process_spider_exception 必须返回 None 或者是一个可迭代对象(其中每个元素都是 Response 或 Item 类型)。若 result 为 None, 则 Scrapy 继续处理该异常, 并依次触发其他中间 middleware 的 process_spider_exception 方法, 直到所有相关 middlewares 完成处理为止(这些异常会被记录但不会影响正常流程)。若 result 是一个可迭代对象, 则会激活 middlewares.process_spider_output, 其他相关的 exception 处理将会停止.

2)Download Middlewares

下载器中间件充当引擎与下载器之间的通信中介:当引擎发送请求至下载器时,该组件可执行预处理操作(如添加http头信息、设置代理信息等)。当 download 器完成 HTTP 请求并返回响应给 engine 时,则可在此组件中执行后端处理(如解压 GZIP 数据等)。此外,在此组件中我们还可以配置反爬机制以规避搜索引擎抓取:例如,在 download 类别中定义两个方法——process_request(self, request, spider)process_response(self, request, response, spider)。前者会在请求被发起前触发;后者则会在 response 被获取前执行数据解析工作。要将此组件启用,则应在 setting.py 配置 DOWNLOADER_MIDDLEWARES 参数:该参数为一个字典结构体,默认值为空列表;其键值对应于指定具体组件类名及优先级排序。

复制代码
 DOWNLOADER_MIDDLEWARES = {

    
     'mySpider.middlewares.MyDownloaderMiddleware': 543, }
    
    
    
    
    代码解读

方法:

复制代码
 process_request(self, request, spider)

    
 # request : 发送请求的request对象。
    
 # spider : 发送请求的spider对象。
    
    
    
    
    代码解读

在下载器发送请求之前实施的该方法,在其内部可以配置随机代理与请求头等参数;通常可以在其内部配置随机代理与请求头等参数

当返回None时:Scrapy将继续执行该请求,并按照中间件流程依次处理相关的方法直至合适的下载器函数被激活。
当返回Response对象时:Scrapy将直接返回该响应对象,并且已经激活的中间件中的process_response()方法将在每次响应返回时被自动调用。
当返回Request对象时:系统将不再使用之前的请求对象来获取数据而是根据限制条件切换为新的请求源以获取数据。
如果在处理过程中发生异常:系统会自动触发并处理相应的异常处理流程即process_exception()方法。

复制代码
 process_response(self, request, response, spider)

    
 # request:request对象。
    
 # response:被处理的response对象。
    
 # spider:spider对象.
    
    
    
    
    代码解读

这个方法是下载器下载的数据到引擎中间会执行的方法。
返回值:

该Response对象会被传递给后续中间件,并最终发送给爬虫。
该Request对象会被处理后重置下载器链。
如果在该方法运行过程中出现异常,则会触发request的errorback方法;若未定义该方法,则直接抛出异常。

(3)settings.py

settings.py 是 spdier 项目的配置文件。

各字段说明如下:

  • BOT_NAME:项目名;
  • USER_AGENT:默认是注释的,这个东西非常重要,如果不写很容易被判断为电脑,简单点设置一个Mozilla/5.0即可;
  • ROBOTSTXT_OBEY:是否遵循机器人协议,默认是true,需要改为 false,否则很多东西爬不了;
  • CONCURRENT_REQUESTS:最大并发数,就是同时允许开启多少个爬虫线程;
  • DOWNLOAD_DELAY:下载延迟时间,单位是秒,控制爬虫爬取的频率,根据你的项目调整,不要太快也不要太慢,默认是3秒,即爬一个停3秒,设置为1秒性价比较高,如果要爬取的文件较多,写零点几秒也行
  • COOKIES_ENABLED:是否保存 COOKIES,默认关闭,开启可以记录爬取过程中的 COOKIE,非常好用的一个参数;
  • DEFAULT_REQUEST_HEADERS:默认请求头,上面写了一个USER_AGENT,其实这个东西就是放在请求头里面的,这个东西可以根据你爬取的内容做相应设置;
  • ITEM_PIPELINES:项目管道,300为优先级,越低越爬取的优先度越高
复制代码
 # Scrapy settings for ps project

    
 #
    
 # For simplicity, this file contains only settings considered important or
    
 # commonly used. You can find more settings consulting the documentation:
    
 #
    
 #     https://docs.scrapy.org/en/latest/topics/settings.html
    
 #     https://docs.scrapy.org/en/latest/topics/downloader-middleware.html
    
 #     https://docs.scrapy.org/en/latest/topics/spider-middleware.html
    
  
    
 BOT_NAME = 'ps'
    
  
    
 SPIDER_MODULES = ['ps.spiders']
    
 NEWSPIDER_MODULE = 'ps.spiders'
    
  
    
  
    
 # Crawl responsibly by identifying yourself (and your website) on the user-agent
    
 # USER_AGENT = 'ps (+http://www.yourdomain.com)'
    
  
    
 # Obey robots.txt rules
    
 ROBOTSTXT_OBEY = False  # 不遵守协议
    
  
    
 # Configure maximum concurrent requests performed by Scrapy (default: 16)
    
 #CONCURRENT_REQUESTS = 32
    
  
    
 # Configure a delay for requests for the same website (default: 0)
    
 # See https://docs.scrapy.org/en/latest/topics/settings.html#download-delay
    
 # See also autothrottle settings and docs
    
 #DOWNLOAD_DELAY = 3
    
 # The download delay setting will honor only one of:
    
 #CONCURRENT_REQUESTS_PER_DOMAIN = 16
    
 #CONCURRENT_REQUESTS_PER_IP = 16
    
  
    
 # Disable cookies (enabled by default)
    
 #COOKIES_ENABLED = False
    
  
    
 # Disable Telnet Console (enabled by default)
    
 #TELNETCONSOLE_ENABLED = False
    
  
    
 # Override the default request headers:  头部
    
 DEFAULT_REQUEST_HEADERS = {
    
   'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8',
    
   'Accept-Language': 'en',
    
     'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/105.0.0.0 Safari/537.36'
    
 }
    
  
    
  
    
 # Enable or disable spider middlewares
    
 # See https://docs.scrapy.org/en/latest/topics/spider-middleware.html
    
 #SPIDER_MIDDLEWARES = {
    
 #    'ps.middlewares.PsSpiderMiddleware': 543,
    
 #}
    
  
    
 # Enable or disable downloader middlewares
    
 # See https://docs.scrapy.org/en/latest/topics/downloader-middleware.html
    
 DOWNLOADER_MIDDLEWARES = {
    
    'ps.middlewares.PsDownloaderMiddleware': 543,
    
 }
    
  
    
 # Enable or disable extensions
    
 # See https://docs.scrapy.org/en/latest/topics/extensions.html
    
 #EXTENSIONS = {
    
 #    'scrapy.extensions.telnet.TelnetConsole': None,
    
 #}
    
  
    
 LOG_LEVEL = 'INFO'
    
 LOG_FILE = './ps.log'
    
  
    
 # Configure item pipelines
    
 # See https://docs.scrapy.org/en/latest/topics/item-pipeline.html
    
 ITEM_PIPELINES = {
    
    'ps.pipelines.PsPipeline': 300,
    
 }
    
  
    
 # Enable and configure the AutoThrottle extension (disabled by default)
    
 # See https://docs.scrapy.org/en/latest/topics/autothrottle.html
    
 #AUTOTHROTTLE_ENABLED = True
    
 # The initial download delay
    
 #AUTOTHROTTLE_START_DELAY = 5
    
 # The maximum download delay to be set in case of high latencies
    
 #AUTOTHROTTLE_MAX_DELAY = 60
    
 # The average number of requests Scrapy should be sending in parallel to
    
 # each remote server
    
 #AUTOTHROTTLE_TARGET_CONCURRENCY = 1.0
    
 # Enable showing throttling stats for every response received:
    
 #AUTOTHROTTLE_DEBUG = False
    
  
    
 # Enable and configure HTTP caching (disabled by default)
    
 # See https://docs.scrapy.org/en/latest/topics/downloader-middleware.html#httpcache-middleware-settings
    
 #HTTPCACHE_ENABLED = True
    
 #HTTPCACHE_EXPIRATION_SECS = 0
    
 #HTTPCACHE_DIR = 'httpcache'
    
 #HTTPCACHE_IGNORE_HTTP_CODES = []
    
 #HTTPCACHE_STORAGE = 'scrapy.extensions.httpcache.FilesystemCacheStorage'
    
    
    
    
    代码解读

(3)items.py

Items 为每个项目创建一个字段存储空间,在此位置上, Scrapy spiders 会将获取到的数据存储下来。爬虫的主要任务是从非结构化数据源中提取结构化的信息,并通常从网页中获取这些数据。尽管简单易用, 但 Python 却缺乏对复杂项目的支持能力, 在一个包含许多 spiders 的大型项目中, 如果在字段名中输入错误或者返回的数据不一致, 就会导致问题出现.为了实现统一的数据格式化输出, scrapy 提供了 item 类, Item 对象是一种简单的容器, 其主要功能是收集提取到的数据. 它们提供了一种直观易懂的接口来声明可用字段.各种 scrapy 组件均能利用 item 提供的相关元数据来确定输出列的具体内容, 同时通过 trackref 跟踪实例以帮助发现潜在的内存泄漏问题.

Item 使用简单的类定义语法和字段对象声明,如下所示:

复制代码
 import scrapy

    
  
    
 class Product(scrapy.Item): 
    
 	# 字段类型就是简单的scrapy.Field
    
     name = scrapy.Field()
    
     price = scrapy.Field()
    
     stock = scrapy.Field()
    
     last_updated = scrapy.Field(serializer=str)
    
    
    
    
    代码解读

该Field对象被设计用于为每一个字段分配相应的属性信息。您可以选择为每一个字段分配各种类型的属性信息。其值域无限制。值得注意的是,在声明特定项时,对应的字段不会被视为类属性;相反地,则可以通过Item.fields获取这些属性信息

使用 Item:

创建 items

复制代码
 product = Product(name='Desktop PC', price=1000)

    
 print product
    
 # Product(name='Desktop PC', price=1000)
    
    
    
    
    代码解读

获取 Field 值

复制代码
 product['name']

    
 # Desktop PC
    
  
    
 product.get('name')
    
 # Desktop PC
    
  
    
 product['last_updated']
    
 # Traceback (most recent call last):
    
 #     ...
    
 # KeyError: 'last_updated'
    
  
    
 product.get('last_updated', 'not set')
    
 # not set
    
  
    
 product['lala'] # getting unknown field
    
 # Traceback (most recent call last):
    
 #     ...
    
 # KeyError: 'lala'
    
  
    
 product.get('lala', 'unknown field')
    
 # 'unknown field'
    
  
    
 'name' in product  
    
 # True
    
  
    
 'last_updated' in product  
    
 # False
    
  
    
 'last_updated' in product.fields 
    
 # True
    
  
    
 'lala' in product.fields 
    
 # False
    
    
    
    
    代码解读

设置 Field 值

复制代码
 product['last_updated'] = 'today'

    
 product['last_updated']
    
 # today
    
  
    
 product['lala'] = 'test' # setting unknown field
    
 # Traceback (most recent call last):
    
 #     ...
    
 # KeyError: 'Product does not support field: lala'
    
    
    
    
    代码解读

获取所有内容

复制代码
 product.keys()

    
 # ['price', 'name']
    
  
    
 product.items()
    
 # [('price', 1000), ('name', 'Desktop PC')]
    
    
    
    
    代码解读

复制 items

复制代码
 product2 = Product(product)

    
 print product2
    
 # Product(name='Desktop PC', price=1000)
    
  
    
 product3 = product2.copy() print product3
    
 # Product(name='Desktop PC', price=1000)
    
    
    
    
    代码解读

从items创建字典

复制代码
 dict(product) # create a dict from all populated values

    
 # {'price': 1000, 'name': 'Desktop PC'}
    
    
    
    
    代码解读

从字典创建 items

复制代码
 Product({'name': 'Laptop PC', 'price': 1500})

    
 # Product(price=1500, name='Laptop PC')
    
  
    
 Product({'name': 'Laptop PC', 'lala': 1500}) # warning: unknown field in dict
    
 # Traceback (most recent call last):
    
 #    ...
    
 # KeyError: 'Product does not support field: lala' ```
    
    
    
    
    代码解读

(5)pipelines.py

Item pipline 的核心职能是管理从网页爬取而来的 Item 数据,并对其执行清洗、验证及存储操作。在页面被蜘蛛解析完成后,在 Item pipline 中接收并按照预定程序对数据进行处理。

每个 Item piple 组件均为一个独立的 Python 类体,在该类体中需具备 process_item(self, item, spider) 功能模块,并对该功能进行调用以完成数据操作。

每一个 Item piple 成员类都必须包含 process_item(self, item, spider) 方法这一核心功能模块,并通过调用该方法对数据进行处理。该方法需返回一个包含数据的字典或 item 对象,并可能触发 DropItem 异常以指示数据应予以丢弃;随后的所有 pipeline 成员将无法接续处理这些未经过操作的数据项。

复制代码
 def download_from_url(url):

    
     response = requests.get(url, stream=True)
    
     if response.status_code == requests.codes.ok:
    
     return response.content
    
     else:
    
     print('%s-%s' % (url, response.status_code))
    
     return None
    
     class SexyPipeline(object):
    
  
    
     def __init__(self):
    
     self.save_path = '/tmp'
    
  
    
     def process_item(self, item, spider):
    
     if spider.name == 'sexy':
    
         # 取出item里内容
    
         img_url = item['img_url']
    
         
    
         # 业务处理
    
         file_name = img_url.split('/')[-1]
    
         content = download_from_url(img_url)
    
         if content is not None:
    
             with open(os.path.join(self.save_path, file_name), 'wb') as fw:
    
                 fw.write(content)
    
     return item
    
    
    
    
    代码解读
  1. 这个process_item()方法有两个参数:一个是Item对象(作为被处理的对象),另一个是Spider对象(用于生成该Item的对象)。
  2. 这个过程_item()方法返回的结果有两种情况:
    a. 如果返回的是Item对象,则该Item会被较低优先级的Item管道中的process_item()方法继续处理。
    b. 如果抛出了DropItem异常,则该Item将被丢弃不再进行后续处理。
  3. 此外还可以选择通过以下方式实现:
复制代码
    open_spider(self,spider)
    
    代码解读

在 Spider 初始化阶段, open_spider() 方法会被自动触发. 在此期间, 可以执行一系列必要的初始设置, 包括但不限于启动数据库连接等关键功能. 其中参数 spider 代表即将启动的 Spider 实例.

复制代码
    close_spider(self,spider)
    
    代码解读

该方法会在 Spider 关闭时自动执行。在此时点上可以执行一些收尾操作,例如关闭数据库连接等。其中参数 spider 即为目标 Spider 对象。

复制代码
    from_crawler(cls,crawler)
    
    代码解读

该方法是从 crawler 引发的,并且已标记为 @classmethod 标识。它采用依赖注入模式,并接受 crawler 参数作为输入。通过接收的 crawler 实例(通常是一个 Scrapy 对象),我们可以获取到该框架的所有核心组件信息(例如全局配置中的各项设置),从而生成相应的管道实例(Pipeline)。其中 cls 参数默认会传递 Class 类型(如果未指定则会使用默认值)。

settings.py 中的 ITEM_PIPELINES 字段中定义完整的类名是开启 piplines.py 中类的前提条件。这样才可以使 piplines.py 中的类得以启用。

(6)pipeline 的优先级

在setting.py中设置各个管道的优先级参数,在较低值时该管道被赋予更高的获取优先度。例如,在pipelines.py中我实现了两个管道:一个是用于抓取网页的内容,另一个是负责将数据存储到数据库中.

setting.py 中调整他们的优先级,如果有爬虫数据,优先执行存库操作。

复制代码
 'scrapyP1.pipelines.BaiduPipeline': 300,

    
     'scrapyP1.pipelines.BaiduMysqlPipeline': 200, }
    
    
    
    
    代码解读

全部评论 (0)

还没有任何评论哟~