十六、 Scrapy 框架介绍与安装
1. Scrapy 框架介绍
- Scrapy是Python开发的一个快速,高层次的屏幕抓取和web抓取框架,用于抓取web站点并从页面中提取结构化的数据。Scrapy = Scrach+Python
- Scrapy用途广泛,可以用于数据挖掘、监测和自动化测试、信息处理和历史档案等大量应用范围内抽取结构化数据的应用程序框架,广泛用于工业
- Scrapy 使用Twisted 这个异步网络库来处理网络通讯,架构清晰,并且包含了各种中间件接口,可以灵活的完成各种需求。Scrapy是由Twisted写的一个受欢迎的Python事件驱动网络框架,它使用的是非堵塞的异步处理
1.1 为什么要使用Scrapy?
- 它更容易构建和大规模的抓取项目
- 它内置的机制被称为选择器,用于从网站(网页)上提取数据
- 它异步处理请求,速度十分快
- 它可以使用自动调节机制自动调整爬行速度
- 确保开发人员可访问性
1.2 Scrapy的特点
- Scrapy是一个开源和免费使用的网络爬虫框架
- Scrapy生成格式导出如:JSON,CSV和XML
- Scrapy内置支持从源代码,使用XPath或CSS表达式的选择器来提取数据
- Scrapy基于爬虫,允许以自动方式从网页中提取数据
1.3 Scrapy的优点
- Scrapy很容易扩展,快速和功能强大;
- 这是一个跨平台应用程序框架(在Windows,Linux,Mac OS和BSD)。
- Scrapy请求调度和异步处理;
- Scrapy附带了一个名为Scrapyd的内置服务,它允许使用JSON Web服务上传项目和控制蜘蛛。
- 也能够刮削任何网站,即使该网站不具有原始数据访问API;
1.4 整体架构大致如下:
最简单的单个网页爬取流程是spiders > scheduler > downloader > spiders > item pipeline
1.5 Scrapy运行流程大概如下:
- 引擎从调度器中取出一个链接(URL)用于接下来的抓取
- 引擎把URL封装成一个请求(Request)传给下载器
- 下载器把资源下载下来,并封装成应答包(Response)
- 爬虫解析Response
- 解析出实体(Item),则交给实体管道进行进一步的处理
- 解析出的是链接(URL),则把URL交给调度器等待抓取
1.6 Scrapy主要包括了以下组件:
- 引擎(Scrapy)
- 用来处理整个系统的数据流处理, 触发事务(框架核心)
- 调度器(Scheduler)
- 用来接受引擎发过来的请求, 压入队列中, 并在引擎再次请求的时候返回. 可以想像成一个URL(抓取网页的网址或者说是链接)的优先队列, 由它来决定下一个要抓取的网址是什么, 同时去除重复的网址
- 下载器(Downloader)
- 用于下载网页内容, 并将网页内容返回给蜘蛛(Scrapy下载器是建立在twisted这个高效的异步模型上的)
- 爬虫(Spiders)
- 爬虫是主要干活的, 用于从特定的网页中提取自己需要的信息, 即所谓的实体(Item)。用户也可以从中提取出链接,让Scrapy继续抓取下一个页面
- 项目管道(Pipeline)
- 负责处理爬虫从网页中抽取的实体,主要的功能是持久化实体、验证实体的有效性、清除不需要的信息。当页面被爬虫解析后,将被发送到项目管道,并经过几个特定的次序处理数据。
- 下载器中间件(Downloader Middlewares)
- 位于Scrapy引擎和下载器之间的框架,主要是处理Scrapy引擎与下载器之间的请求及响应
- 爬虫中间件(Spider Middlewares)
- 介于Scrapy引擎和爬虫之间的框架,主要工作是处理蜘蛛的响应输入和请求输出
- 调度中间件(Scheduler Middewares)
- 介于Scrapy引擎和调度之间的中间件,从Scrapy引擎发送到调度的请求和响应
2 安装
pip install Scrapy
注:windows平台需要依赖pywin32
ModuleNotFoundError: No module named 'win32api'
pip install pypiwin32
十七、Scrapy 框架使用
1 基本使用
1.1 创建项目
运行命令: scrapy startproject myfrist(your_project_name)
文件说明:
名称作用scrapy.cfg项目的配置信息,主要为Scrapy命令行工具提供一个基础的配置信息。(真正爬虫相关的配置信息在settings.py文件中)items.py设置数据存储模板,用于结构化数据,如:Django的Modelpipelines数据处理行为,如:一般结构化的数据持久化settings.py配置文件,如:递归的层数、并发数,延迟下载等spiders爬虫目录,如:创建文件,编写爬虫规则
注意:一般创建爬虫文件时,以网站域名命名
2 编写 spdier
在spiders目录中新建 daidu_spider.py 文件
2.1 注意
- 爬虫文件需要定义一个类,并继承scrapy.spiders.Spider
- 必须定义name,即爬虫名,如果没有name,会报错。因为源码中是这样定义的
2.2 编写内容
在这里可以告诉 scrapy 。要如何查找确切数据,这里必须要定义一些属性
- name: 它定义了蜘蛛的唯一名称
- allowed_domains: 它包含了蜘蛛抓取的基本URL;
- start-urls: 蜘蛛开始爬行的URL列表;
- parse(): 这是提取并解析刮下数据的方法;
下面的代码演示了蜘蛛代码的样子:
import scrapy
class DoubanSpider(scrapy.Spider):
name = 'douban'
allwed_url = 'douban.com'
start_urls = [
'https://movie.douban.com/top250/'
]
def parse(self, response):
movie_name = response.xpath("//div[@class='item']//a/span[1]/text()").extract()
movie_core = response.xpath("//div[@class='star']/span[2]/text()").extract()
yield {
'movie_name':movie_name,
'movie_core':movie_core
}
其他命令:
- 创建爬虫
scrapy genspider 爬虫名 爬虫的地址 - 运行爬虫
scrapy crawl 爬虫名
总结:
1.创建项目:scrapy startproject 项目名称。(例如:scrapy startproject book)
2.创建爬虫:scrapy genspider 爬虫名 爬虫的地址。(例如: scrapy genspider zongheng http://zongheng.com)
3.运行爬虫:
(1)、scrapy crawl 爬虫名。(例如:scrapy crawl zongheng)
(2)、在 spiders 目录下创建一个用于开始的 .py 文件。 输入以下命令,并执行该 .py 文件,以达到运行爬虫的目的。
例如:在 spiders 目录下创建: begin.py 代码如下
from scrapy.cmdline import execute
execute("scrapy crawl zongheng".split())
十八、Scrapy 数据的提取
1 Scrapy提取项目
从网页中提取数据,Scrapy 使用基于 XPath 和 CSS 表达式的技术叫做选择器。以下是 XPath 表达式的一些例子:
- 这将选择 HTML 文档中的
<head>
元素中的<title>
元素
/html/head/title
- 这将选择
<title>
元素中的文本
/html/head/title/text()
- 这将选择所有的
<td>
元素
//td
- 选择 div 包含一个属性 class=”slice” 的所有元素
//div[@class=”slice”]
选择器有四个基本的方法,如下所示:
S.N.方法 & 描述extract()它返回一个unicode字符串以及所选数据extract_first()它返回第一个unicode字符串以及所选数据re()它返回Unicode字符串列表,当正则表达式被赋予作为参数时提取xpath()它返回选择器列表,它代表由指定XPath表达式参数选择的节点css()它返回选择器列表,它代表由指定CSS表达式作为参数所选择的节点
2 Scrapy Shell
如果使用选择器想快速的到到效果,我们可以使用Scrapy Shell
scrapy shell "http://www.163.com"
注意windows系统必须使用双引号
2.1 举例
从一个普通的HTML网站提取数据,查看该网站得到的 XPath 的源代码。检测后,可以看到数据将在UL标签,并选择 li 标签中的 元素。
代码的下面行显示了不同类型的数据的提取:
- 选择 li 标签内的数据:
response.xpath('//ul/li')
- 对于选择描述:
response.xpath('//ul/li/text()').extract()
- 对于选择网站标题:
response.xpath('//ul/li/a/text()').extract()
- 对于选择网站的链接:
response.xpath('//ul/li/a/@href').extract()
十九、Scrapy数据的保存
1. 数据的提取
1.1 控制台打印
import scrapy
class DoubanSpider(scrapy.Spider):
name = 'douban'
allwed_url = 'douban.com'
start_urls = [
'https://movie.douban.com/top250/'
]
def parse(self, response):
movie_name = response.xpath("//div[@class='item']//a/span[1]/text()").extract()
movie_core = response.xpath("//div[@class='star']/span[2]/text()").extract()
yield {
'movie_name':movie_name,
'movie_core':movie_core
}
执行以上代码,我可以在控制看到:
2018-01-24 15:17:14 [scrapy.utils.log] INFO: Scrapy 1.5.0 started (bot: spiderdemo1)
2018-01-24 15:17:14 [scrapy.utils.log] INFO: Versions: lxml 4.1.1.0, libxml2 2.9.5, cssselect 1.0.3, parsel 1.3.1, w3lib 1.18.0, Twiste
d 17.9.0, Python 3.6.3 (v3.6.3:2c5fed8, Oct 3 2017, 18:11:49) [MSC v.1900 64 bit (AMD64)], pyOpenSSL 17.5.0 (OpenSSL 1.1.0g 2 Nov 201
7), cryptography 2.1.4, Platform Windows-10-10.0.10240-SP0
2018-01-24 15:17:14 [scrapy.crawler] INFO: Overridden settings: {'BOT_NAME': 'spiderdemo1', 'NEWSPIDER_MODULE': 'spiderdemo1.spiders',
'ROBOTSTXT_OBEY': True, 'SPIDER_MODULES': ['spiderdemo1.spiders']}
2018-01-24 15:17:14 [scrapy.middleware] INFO: Enabled extensions:
['scrapy.extensions.corestats.CoreStats',
'scrapy.extensions.telnet.TelnetConsole',
'scrapy.extensions.logstats.LogStats']
2018-01-24 15:17:14 [scrapy.middleware] INFO: Enabled downloader middlewares:
['scrapy.downloadermiddlewares.robotstxt.RobotsTxtMiddleware',
'scrapy.downloadermiddlewares.httpauth.HttpAuthMiddleware',
'scrapy.downloadermiddlewares.downloadtimeout.DownloadTimeoutMiddleware',
'scrapy.downloadermiddlewares.defaultheaders.DefaultHeadersMiddleware',
'scrapy.downloadermiddlewares.useragent.UserAgentMiddleware',
'scrapy.downloadermiddlewares.retry.RetryMiddleware',
'scrapy.downloadermiddlewares.redirect.MetaRefreshMiddleware',
'scrapy.downloadermiddlewares.httpcompression.HttpCompressionMiddleware',
'scrapy.downloadermiddlewares.redirect.RedirectMiddleware',
'scrapy.downloadermiddlewares.cookies.CookiesMiddleware',
'scrapy.downloadermiddlewares.httpproxy.HttpProxyMiddleware',
'scrapy.downloadermiddlewares.stats.DownloaderStats']
2018-01-24 15:17:14 [scrapy.middleware] INFO: Enabled spider middlewares:
['scrapy.spidermiddlewares.httperror.HttpErrorMiddleware',
'scrapy.spidermiddlewares.offsite.OffsiteMiddleware',
'scrapy.spidermiddlewares.referer.RefererMiddleware',
'scrapy.spidermiddlewares.urllength.UrlLengthMiddleware',
'scrapy.spidermiddlewares.depth.DepthMiddleware']
2018-01-24 15:17:14 [scrapy.middleware] INFO: Enabled item pipelines:
[]
2018-01-24 15:17:14 [scrapy.core.engine] INFO: Spider opened
2018-01-24 15:17:14 [scrapy.extensions.logstats] INFO: Crawled 0 pages (at 0 pages/min), scraped 0 items (at 0 items/min)
2018-01-24 15:17:14 [scrapy.extensions.telnet] DEBUG: Telnet console listening on 127.0.0.1:6023
2018-01-24 15:17:14 [scrapy.core.engine] DEBUG: Crawled (200) <GET https://movie.douban.com/robots.txt> (referer: None)
2018-01-24 15:17:15 [scrapy.downloadermiddlewares.redirect] DEBUG: Redirecting (301) to <GET https://movie.douban.com/top250> from <GET
https://movie.douban.com/top250/>
2018-01-24 15:17:15 [scrapy.core.engine] DEBUG: Crawled (200) <GET https://movie.douban.com/top250> (referer: None)
2018-01-24 15:17:15 [scrapy.core.scraper] DEBUG: Scraped from <200 https://movie.douban.com/top250>
{'movie_name': ['肖申克的救赎', '霸王别姬', '这个杀手不太冷', '阿甘正传', '美丽人生', '千与千寻', '泰坦尼克号', '辛德勒的名单', '盗梦空
间', '机器人总动员', '海上钢琴师', '三傻大闹宝莱坞', '忠犬八公的故事', '放牛班的春天', '大话西游之大圣娶亲', '教父', '龙猫', '楚门的世
界', '乱世佳人', '熔炉', '触不可及', '天堂电影院', '当幸福来敲门', '无间道', '星际穿越'], 'movie_core': ['9.6', '9.5', '9.4', '9.4', '9
.5', '9.2', '9.2', '9.4', '9.3', '9.3', '9.2', '9.1', '9.2', '9.2', '9.2', '9.2', '9.1', '9.1', '9.2', '9.2', '9.1', '9.1', '8.9', '9.0
', '9.1']}
2018-01-24 15:17:15 [scrapy.core.engine] INFO: Closing spider (finished)
2018-01-24 15:17:15 [scrapy.statscollectors] INFO: Dumping Scrapy stats:
{'downloader/request_bytes': 651,
'downloader/request_count': 3,
'downloader/request_method_count/GET': 3,
'downloader/response_bytes': 13900,
'downloader/response_count': 3,
'downloader/response_status_count/200': 2,
'downloader/response_status_count/301': 1,
'finish_reason': 'finished',
'finish_time': datetime.datetime(2018, 1, 24, 7, 17, 15, 247183),
'item_scraped_count': 1,
'log_count/DEBUG': 5,
'log_count/INFO': 7,
'response_received_count': 2,
'scheduler/dequeued': 2,
'scheduler/dequeued/memory': 2,
'scheduler/enqueued': 2,
'scheduler/enqueued/memory': 2,
'start_time': datetime.datetime(2018, 1, 24, 7, 17, 14, 784782)}
2018-01-24 15:17:15 [scrapy.core.engine] INFO: Spider closed (finished)
1.2 以文件的方式输出
1.2.1 python原生方式
with open("movie.txt", 'wb') as f:
for n, c in zip(movie_name, movie_core):
str = n+":"+c+"\n"
f.write(str.encode())
1.2.2 以scrapy内置方式
scrapy 内置主要有四种:JSON,JSON lines,CSV,XML
我们将结果用最常用的JSON导出,命令如下:
scrapy crawl dmoz -o douban.json -t json
-o 后面是导出文件名,-t 后面是导出类型
2 提取内容的封装Item
Scrapy进程可通过使用蜘蛛提取来自网页中的数据。Scrapy使用Item类生成输出对象用于收刮数据
Item 对象是自定义的python字典,可以使用标准字典语法获取某个属性的值
2.1 定义
import scrapy
class InfoItem(scrapy.Item):
# define the fields for your item here like:
movie_name = scrapy.Field()
movie_core = scrapy.Field()
2.2 使用
def parse(self, response):
movie_name = response.xpath("//div[@class='item']//a/span[1]/text()").extract()
movie_core = response.xpath("//div[@class='star']/span[2]/text()").extract()
for n, c in zip(movie_name, movie_core):
movie = InfoItem()
movie['movie_name'] = n
movie['movie_core'] = c
yield movie
二十、Scrapy框架-Pipeline
1. Item Pipeline 介绍
当Item 在Spider中被收集之后,就会被传递到Item Pipeline中进行处理
每个item pipeline组件是实现了简单的方法的python类,负责接收到item并通过它执行一些行为,同时也决定此Item是否继续通过pipeline,或者被丢弃而不再进行处理
item pipeline的主要作用:
- 清理html数据
- 验证爬取的数据
- 去重并丢弃
- 讲爬取的结果保存到数据库中或文件中
2. 编写自己的item pipeline
2.1 必须实现的函数
- process_item(self,item,spider)
每个item piple组件是一个独立的pyhton类,必须实现以process_item(self,item,spider)方法
每个item pipeline组件都需要调用该方法,这个方法必须返回一个具有数据的dict,或者item对象,或者抛出DropItem异常,被丢弃的item将不会被之后的pipeline组件所处理
2.2 可以选择实现
- open_spider(self,spider) 表示当spider被开启的时候调用这个方法
- close_spider(self,spider) 当spider关闭时候这个方法被调用
2.3 应用到项目
import json
class MoviePipeline(object):
def process_item(self, item, spider):
json.dump(dict(item), open('diban.json', 'a', encoding='utf-8'), ensure_ascii=False)
return item
注意:
写到pipeline后,要在settings中设置才可生效
ITEM_PIPELINES = {
'spiderdemo1.pipelines.MoviePipeline': 300
}
2.4 将项目写入MongoDB
MongoDB地址和数据库名称在Scrapy设置中指定; MongoDB集合以item类命名
from pymongo import MongoClient
from middle.settings import HOST
from middle.settings import PORT
from middle.settings import DB_NAME
from middle.settings import SHEET_NAME
class MiddlePipeline(object):
def __init__(self):
client = MongoClient(host=HOST, port=PORT)
my_db = client[DB_NAME]
self.sheet = my_db[SHEET_NAME]
def process_item(self, item, spider):
self.sheet.insert(dict(item))
return item
二十一、Scrapy框架-settings
Scrapy内置设置
下面给出scrapy提供的常用内置设置列表,你可以在settings.py文件里面修改这些设置,以应用或者禁用这些设置项
- BOT_NAME
默认: 'scrapybot'
Scrapy项目实现的bot的名字。用来构造默认 User-Agent,同时也用来log。 当你使用 startproject 命令创建项目时其也被自动赋值。 - CONCURRENT_ITEMS
默认: 100
Item Processor(即 Item Pipeline) 同时处理(每个response的)item的最大值 - CONCURRENT_REQUESTS
默认: 16
Scrapy downloader 并发请求(concurrent requests)的最大值。 - CONCURRENT_REQUESTS_PER_DOMAIN
默认: 8
对单个网站进行并发请求的最大值。 - CONCURRENT_REQUESTS_PER_IP
默认: 0
对单个IP进行并发请求的最大值。如果非0,则忽略 CONCURRENT_REQUESTS_PER_DOMAIN 设定, 使用该设定。 也就是说,并发限制将针对IP,而不是网站。
该设定也影响 DOWNLOAD_DELAY: 如果 CONCURRENT_REQUESTS_PER_IP 非0,下载延迟应用在IP而不是网站上。 - DEFAULT_ITEM_CLASS
默认: 'scrapy.item.Item'
the Scrapy shell 中实例化item使用的默认类 - DEFAULT_REQUEST_HEADERS
默认:
{ 'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8', 'Accept-Language': 'en', }
Scrapy HTTP Request使用的默认header。由 DefaultHeadersMiddleware 产生。 - DOWNLOADER
默认: 'scrapy.core.downloader.Downloader'
用于crawl的downloader. - DOWNLOADER_MIDDLEWARES
默认:: {}
保存项目中启用的下载中间件及其顺序的字典 - DOWNLOAD_DELAY
默认: 0
下载器在下载同一个网站下一个页面前需要等待的时间。该选项可以用来限制爬取速度, 减轻服务器压力。同时也支持小数 - DOWNLOAD_HANDLERS
默认: {}
保存项目中启用的下载处理器(request downloader handler)的字典 - DOWNLOAD_TIMEOUT
默认: 180
下载器超时时间(单位: 秒) - EXTENSIONS
默认:{}
保存项目中启用的插件及其顺序的字典 - ITEM_PIPELINES
默认: {}
保存项目中启用的pipeline及其顺序的字典。该字典默认为空,值(value)任意。 不过值(value)习惯设定在0-1000范围内 - ITEM_PIPELINES_BASE
默认: {}
保存项目中默认启用的pipeline的字典。 永远不要在项目中修改该设定,而是修改 ITEM_PIPELINES - LOG_ENABLED
默认: True
是否启用logging - LOG_ENCODING
默认: 'utf-8'
logging使用的编码。 - LOG_FILE
默认: None
logging输出的文件名。如果为None,则使用标准错误输出(standard error)。 - LOG_FORMAT
默认: '%(asctime)s [%(name)s] %(levelname)s: %(message)s'
日志的数据格式 - LOG_DATEFORMAT
默认: '%Y-%m-%d %H:%M:%S'
日志的日期格式 - LOG_LEVEL
默认: 'DEBUG'
log的最低级别。可选的级别有: CRITICAL、 ERROR、WARNING、INFO、DEBUG - LOG_STDOUT
默认: False
如果为 True ,进程所有的标准输出(及错误)将会被重定向到log中 - RANDOMIZE_DOWNLOAD_DELAY
默认: True
如果启用,当从相同的网站获取数据时,Scrapy将会等待一个随机的值 (0.5到1.5之间的一个随机值 * DOWNLOAD_DELAY)
该随机值降低了crawler被检测到(接着被block)的机会。某些网站会分析请求, 查找请求之间时间的相似性 - REDIRECT_MAX_TIMES
默认: 20
定义request允许重定向的最大次数。超过该限制后该request直接返回获取到的结果。 对某些任务我们使用Firefox默认值 - ROBOTSTXT_OBEY
默认: True
是否遵循robots协议 - SCHEDULER 默认: 'scrapy.core.scheduler.Scheduler'
用于爬取的调度器 - SPIDER_MIDDLEWARES
默认: {}
保存项目中启用的下载中间件及其顺序的字典 - USER_AGENT
默认: "Scrapy/VERSION (+http://scrapy.org)"
爬取的默认User-Agent,除非被覆盖
Scrapy默认BASE设置
scrapy对某些内部组件进行了默认设置,这些组件通常情况下是不能被修改的,但是我们在自定义了某些组件以后,比如我们设置了自定义的middleware中间件,需要按照一定的顺序把他添加到组件之中,这个时候需要参考scrapy的默认设置,因为这个顺序会影响scrapy的执行,下面列出了scrapy的默认基础设置
注意:如果你想要修改以下的某些设置,应该避免直接修改下列内容,而是修改其对应的自定义内容,例如,你想修改下面的DOWNLOADER_MIDDLEWARES_BASE
的内容,你应该去修改DOWNLOADER_MIDDLEWARES
这个内容,只是去掉了_BASE而已,其他的也是类似这样
- DOWNLOADER_MIDDLEWARES_BASE
默认:
{
'scrapy.downloadermiddlewares.robotstxt.RobotsTxtMiddleware': 100,
'scrapy.downloadermiddlewares.httpauth.HttpAuthMiddleware': 300,
'scrapy.downloadermiddlewares.downloadtimeout.DownloadTimeoutMiddleware': 350,
'scrapy.downloadermiddlewares.useragent.UserAgentMiddleware': 400,
'scrapy.downloadermiddlewares.retry.RetryMiddleware': 500,
'scrapy.downloadermiddlewares.defaultheaders.DefaultHeadersMiddleware': 550,
'scrapy.downloadermiddlewares.redirect.MetaRefreshMiddleware': 580,
'scrapy.downloadermiddlewares.httpcompression.HttpCompressionMiddleware': 590,
'scrapy.downloadermiddlewares.redirect.RedirectMiddleware': 600,
'scrapy.downloadermiddlewares.cookies.CookiesMiddleware': 700,
'scrapy.downloadermiddlewares.httpproxy.HttpProxyMiddleware': 750,
'scrapy.downloadermiddlewares.chunked.ChunkedTransferMiddleware': 830,
'scrapy.downloadermiddlewares.stats.DownloaderStats': 850,
'scrapy.downloadermiddlewares.httpcache.HttpCacheMiddleware': 900,
}
包含Scrapy默认启用的下载中间件的字典。 永远不要在项目中修改该设定,而是修改 DOWNLOADER_MIDDLEWARES 。
- SPIDER_MIDDLEWARES_BASE
默认:
{
'scrapy.spidermiddlewares.httperror.HttpErrorMiddleware': 50,
'scrapy.spidermiddlewares.offsite.OffsiteMiddleware': 500,
'scrapy.spidermiddlewares.referer.RefererMiddleware': 700,
'scrapy.spidermiddlewares.urllength.UrlLengthMiddleware': 800,
'scrapy.spidermiddlewares.depth.DepthMiddleware': 900,
}
保存项目中默认启用的spider中间件的字典。 永远不要在项目中修改该设定,而是修改 SPIDER_MIDDLEWARES 。 EXTENSIONS_BASE
默认:
{
'scrapy.extensions.corestats.CoreStats': 0,
'scrapy.telnet.TelnetConsole': 0,
'scrapy.extensions.memusage.MemoryUsage': 0,
'scrapy.extensions.memdebug.MemoryDebugger': 0,
'scrapy.extensions.closespider.CloseSpider': 0,
'scrapy.extensions.feedexport.FeedExporter': 0,
'scrapy.extensions.logstats.LogStats': 0,
'scrapy.extensions.spiderstate.SpiderState': 0,
'scrapy.extensions.throttle.AutoThrottle': 0,
}
可用的插件列表。需要注意,有些插件需要通过设定来启用。默认情况下, 该设定包含所有稳定(stable)的内置插件。
- DOWNLOAD_HANDLERS_BASE
默认:
{
'file': 'scrapy.core.downloader.handlers.file.FileDownloadHandler',
'http': 'scrapy.core.downloader.handlers.http.HttpDownloadHandler',
'https': 'scrapy.core.downloader.handlers.http.HttpDownloadHandler',
's3': 'scrapy.core.downloader.handlers.s3.S3DownloadHandler',
}
保存项目中默认启用的下载处理器(request downloader handler)的字典。 永远不要在项目中修改该设定,而是修改 DOWNLOADER_HANDLERS 。
如果需要关闭上面的下载处理器,您必须在项目中的 DOWNLOAD_HANDLERS 设定中设置该处理器,并为其赋值为 None 。
说明
即使我们添加了一些我们自定义的组件,scrapy默认的base设置依然会被应用,这样说可能会一头雾水,简单地例子:
假如我们在middlewares.py文件中定义了一个中间件,名称为MyMiddleware,我们把它添加到settings.py文件里面的DOWNLOADER_MIDDLEWARES
,且他的执行顺序我们设置为450,最终的设置内容就是:
DOWNLOADER_MIDDLEWARES = {
'cnblog.middlewares.MyMiddleware':450,
}
我们再来看一下默认的DOWNLOADER_MIDDLEWARES_BASE
的内容:
DOWNLOADER_MIDDLEWARES_BASE ={
'scrapy.downloadermiddlewares.robotstxt.RobotsTxtMiddleware': 100,
'scrapy.downloadermiddlewares.httpauth.HttpAuthMiddleware': 300,
'scrapy.downloadermiddlewares.downloadtimeout.DownloadTimeoutMiddleware': 350,
'scrapy.downloadermiddlewares.useragent.UserAgentMiddleware': 400,
'scrapy.downloadermiddlewares.retry.RetryMiddleware': 500,
'scrapy.downloadermiddlewares.defaultheaders.DefaultHeadersMiddleware': 550,
'scrapy.downloadermiddlewares.redirect.MetaRefreshMiddleware': 580,
'scrapy.downloadermiddlewares.httpcompression.HttpCompressionMiddleware': 590,
'scrapy.downloadermiddlewares.redirect.RedirectMiddleware': 600,
'scrapy.downloadermiddlewares.cookies.CookiesMiddleware': 700,
'scrapy.downloadermiddlewares.httpproxy.HttpProxyMiddleware': 750,
'scrapy.downloadermiddlewares.chunked.ChunkedTransferMiddleware': 830,
'scrapy.downloadermiddlewares.stats.DownloaderStats': 850,
'scrapy.downloadermiddlewares.httpcache.HttpCacheMiddleware': 900,
}
这个时候,scrapy下载中间件的最终的执行顺序就是,把DOWNLOADER_MIDDLEWARES
和DOWNLOADER_MIDDLEWARES_BASE
里面的中间件按照顺序执行,100>300>350>400>450>500>550>580>590>600>700>750>830>850>900
且全部执行,并不会因为我们定义了一个中间件,而使默认的中间件失效,也就是说,最终的结果其实是合并执行。
如果我们不想应用某一个默认的中间件,假如'scrapy.downloadermiddlewares.retry.RetryMiddleware': 500,
那么,就应该在DOWNLOADER_MIDDLEWARES
里面把它的值设置为None,像下面这样:
DOWNLOADER_MIDDLEWARES = {
'cnblog.middlewares.MyMiddleware':450,
'scrapy.downloadermiddlewares.retry.RetryMiddleware':None,
}
二十二、Scrapy框架-案例实现
爬取小说
spider
import scrapy
from xiaoshuo.items import XiaoshuoItem
class XiaoshuoSpiderSpider(scrapy.Spider):
name = 'xiaoshuo_spider'
allowed_domains = ['zy200.com']
url = 'http://www.zy200.com/5/5943/'
start_urls = [url + '11667352.html']
def parse(self, response):
info = response.xpath("/html/body/div[@id='content']/text()").extract()
href = response.xpath("//div[@class='zfootbar']/a[3]/@href").extract_first()
xs_item = XiaoshuoItem()
xs_item['content'] = info
yield xs_item
if href != 'index.html':
new_url = self.url + href
yield scrapy.Request(new_url, callback=self.parse)
items
import scrapy
class XiaoshuoItem(scrapy.Item):
# define the fields for your item here like:
content = scrapy.Field()
href = scrapy.Field()
pipeline
class XiaoshuoPipeline(object):
def __init__(self):
self.filename = open("dp1.txt", "w", encoding="utf-8")
def process_item(self, item, spider):
content = item["title"] + item["content"] + '\n'
self.filename.write(content)
self.filename.flush()
return item
def close_spider(self, spider):
self.filename.close()