写一个爬虫,须要作不少的事情。好比:发送网络请求、数据解析、数据存储、反反爬虫机制(更换ip代理、设置请求头等)、异步请求等。这些工做若是每次都要本身从零开始写的话,比较浪费时间。所以Scrapy
把一些基础的东西封装好了,在他上面写爬虫能够变的更加的高效(爬取效率和开发效率)。所以真正在公司里,一些上了量的爬虫,都是使用Scrapy
框架来解决。php
Scrapy框架模块功能:css
Scrapy Engine(引擎)
:Scrapy
框架的核心部分。负责在Spider
和ItemPipeline
、Downloader
、Scheduler
中间通讯、传递数据等。Spider(爬虫)
:发送须要爬取的连接给引擎,最后引擎把其余模块请求回来的数据再发送给爬虫,爬虫就去解析想要的数据。这个部分是咱们开发者本身写的,由于要爬取哪些连接,页面中的哪些数据是咱们须要的,都是由程序员本身决定。Scheduler(调度器)
:负责接收引擎发送过来的请求,并按照必定的方式进行排列和整理,负责调度请求的顺序等。Downloader(下载器)
:负责接收引擎传过来的下载请求,而后去网络上下载对应的数据再交还给引擎。Item Pipeline(管道)
:负责将Spider(爬虫)
传递过来的数据进行保存。具体保存在哪里,应该看开发者本身的需求。Downloader Middlewares(下载中间件)
:能够扩展下载器和引擎之间通讯功能的中间件。你可用该中间件作如下几件事
Spider Middlewares(Spider中间件)
:能够扩展引擎和爬虫之间通讯功能的中间件。在Scrapy的数据流是由执行引擎控制,具体流程以下:html
pip install scrapy
便可安装。#Windows平台 一、pip3 install wheel #安装后,便支持经过wheel文件安装软件,wheel文件官网:https://www.lfd.uci.edu/~gohlke/pythonlibs 3、pip3 install lxml 4、pip3 install pyopenssl 五、下载并安装pywin32:https://sourceforge.net/projects/pywin32/files/pywin32/ 六、下载twisted的wheel文件:http://www.lfd.uci.edu/~gohlke/pythonlibs/#twisted 七、执行pip3 install 下载目录\Twisted-17.9.0-cp36-cp36m-win_amd64.whl 8、pip3 install scrapy #Linux平台 1、pip3 install scrapy 注意:
若是windows环境下直接经过pip install scrapy命令行安装,报如下错误时: 在windows系统下,提示错误ModuleNotFoundError: No module named 'win32api',那么使用如下命令能够解决:pip install pypiwin32。 在windows系统下,提示错误:error: Microsoft Visual C++ 14.0 is required.那么能够在网址https://www.lfd.uci.edu/~gohlke/pythonlibs/下载Twisted模块,安装该模块后,再从新使用命令行安装pip install scrapy安装scrapy模块
2.2.1 建立项目python
要使用Scrapy
框架建立项目,须要经过命令来建立。首先进入到你想把这个项目存放的目录。而后使用如下命令建立:程序员
scrapy startproject [项目名称]
2.2.2 建立爬虫web
建立爬虫:进入到项目所在的路径,执行命令“scrapy genspider [爬虫名] [爬虫域名]”ajax
注意:爬虫名不能和建立的项目名一致正则表达式
建立完项目和爬虫后,目录结构以下图:shell
项目中主要文件的做用:json
items
的模型存储到本地磁盘中。#1 查看帮助 scrapy -h scrapy <command> -h #2 有两种命令:其中Project-only必须切到项目文件夹下才能执行,而Global的命令则不须要 Global commands: startproject #建立项目 genspider #建立爬虫程序 settings #若是是在项目目录下,则获得的是该项目的配置 runspider #运行一个独立的python文件,没必要建立项目 shell #scrapy shell url地址 在交互式调试,如选择器规则正确与否 fetch #独立于程单纯地爬取一个页面,能够拿到请求头 view #下载完毕后直接弹出浏览器,以此能够分辨出哪些数据是ajax请求 version #scrapy version 查看scrapy的版本,scrapy version -v查看scrapy依赖库的版本 Project-only commands: crawl #运行爬虫,必须建立项目才行,确保配置文件中ROBOTSTXT_OBEY = False check #检测项目中有无语法错误 list #列出项目中所包含的爬虫名 edit #编辑器,通常不用 parse #scrapy parse url地址 --callback 回调函数 #以此能够验证咱们的回调函数是否正确 bench #scrapy bentch压力测试 #3 官网连接 https://docs.scrapy.org/en/latest/topics/commands.html
2.4.1 使用命令建立一个爬虫
scrapy gensipder qsbk_spider "qiushibaike.com"
建立了一个名字叫作qsbk_spider
的爬虫,而且能爬取的网页只会限制在qiushibaike.com
这个域名下。
# -*- coding: utf-8 -*- import scrapy class QsbkSpiderSpider(scrapy.Spider): name = 'qsbk_spider' allowed_domains = ['qiushibaike.com'] start_urls = ['http://qiushibaike.com/'] def parse(self, response): pass
其实这些代码咱们彻底能够本身手动去写,而不用命令。只不过是不用命令,本身写这些代码比较麻烦。
要建立一个Spider,那么必须自定义一个类,继承自scrapy.Spider
,而后在这个类中定义三个属性和一个方法。
parse
方法。这个是个固定的写法。这个方法的做用有两个,第一个是提取想要的数据。第二个是生成下一个请求的url。settings.py
代码在作一个爬虫以前,必定要记得修改setttings.py
中的设置。两个地方是强烈建议设置的。
ROBOTSTXT_OBEY
设置为False。默认是True。即遵照机器协议,那么在爬虫的时候,scrapy首先去找robots.txt文件,若是没有找到。则直接中止爬取。DEFAULT_REQUEST_HEADERS
添加User-Agent
。这个也是告诉服务器,我这个请求是一个正常的请求,不是一个爬虫。爬虫部分代码:
# -*- coding: utf-8 -*- import scrapy from qsbk.items import QsbkItem class QsbkSpiderSpider(scrapy.Spider): name = 'qsbk_spider' allowed_domains = ['qiushibaike.com'] start_urls = ['https://www.qiushibaike.com/text/page/1/'] base_domain = "https://www.qiushibaike.com" def parse(self, response): duanzidivs = response.xpath('//div[@id="content-left"]/div') for duanzidiv in duanzidivs: author = duanzidiv.xpath('.//h2/text()').get().strip() content = duanzidiv.xpath('.//div[@class="content"]//text()').getall() content = ''.join(content).strip() item = QsbkItem(author=author,content=content) yield item next_url = response.xpath('//ul[@class="pagination"]/li[last()]/a/@href').get() if not next_url: return else: yield scrapy.Request(self.base_domain+next_url,callback= self.parse)
items.py部分代码:
import scrapy class QsbkItem(scrapy.Item): author = scrapy.Field() content = scrapy.Field()
pipeline部分代码:
-*- coding: utf-8 -*- # Define your item pipelines here # # Don't forget to add your pipeline to the ITEM_PIPELINES setting # See: https://doc.scrapy.org/en/latest/topics/item-pipeline.html import json class QsbkPipeline(object): def __init__(self): self.fp = open('duanzi.json','w',encoding='utf-8') def open_spider(self,spider): pass def process_item(self, item, spider): item_json = json.dumps(dict(item),ensure_ascii=False) self.fp.write(item_json+'\n') return item def close_spider(self,spider): self.fp.close()
运行scrapy项目。须要在终端,进入项目所在的路径,而后scrapy crawl [爬虫名字]
便可运行指定的爬虫。若是不想每次都在命令行中运行,那么能够把这个命令写在一个文件中。之后就在pycharm中执行运行这个文件就能够了。好比如今新建立一个文件叫作start.py
,而后在这个文件中填入如下代码:
from scrapy import cmdline cmdline.execute(["scrapy","crawl","qsbk_spider"])
#cmdline.execute("scrapy crawl qsbk_spider".split())
2.4.6 糗事百科scrapy爬虫笔记
1.parse(self, response)中的response是一个'scrapy.http.response.html.HtmlResponse'对象。能够执行'xpath'和'css'语法来提取数据。
2.提出出来的数据是一个'Selector'或者'Selectorlist'对象,若是想要获取其中的字符串,能够经过getall()或者get()方法。
3.getall()方法获取‘Selector’中的全部文本,返回的是一个列表。get()方法获取的是‘Selector’中的第一个文本,返回的是一个str类型。
4.若是数据解析完成后,要传给pipline处理,可使用'yield'来返回,或者是收取全部的item,组合成一个列表,最后统一使用return返回。
5.item:建议在'items.py'中定义好要传递的数据。
6.pipeline:这个是专门用来保存数据的,其中有三个方法常常会用到。
* "open_spider(self,spider)":当爬虫被打开时执行。
* "process_item(self,item,spider)":当爬虫有item传过来时被调用。
* "close_spider(self,spider)":当爬虫关闭的时候被调用。
要激活pipeline,须要在'settings.py中设置"ITEM_PIPELINES"。示例以下:
ITEM_PIPELINES = {
'qsbk.pipelines.QsbkPipeline': 300,
}
7.保存json数据的时候,可使用JsonItemExporter和JsonLinesItemExporter类,优化数据存储方式
* JsonItemExporter:每次把数据添加到内存中,最后统一写入到磁盘。优势:存储的数据是一个知足json规则的数据。缺点:当数据量很大的时候比较耗内存。示例代码以下:
from scrapy.exporters import JsonItemExporter class QsbkPipeline(object): def __init__(self): self.fp = open('duanzi.json','wb') self.exporter = JsonItemExporter(self.fp,ensure_ascii = False,encoding = 'utf-8') self.exporter.start_exporting() def open_spider(self,spider): print('爬虫开始了...') def process_item(self, item, spider): self.exporter.export_item(item) return item def close_spider(self,spider): self.exporter.finish_exporting() self.fp.close() print('爬虫结束')
* JsonLinesItemExporter:这个是每次调用export_item的时候就把这个item存储到硬盘中,缺点:每一个字典是一行,整个文件不是一个知足json格式的文件。优势:每次处理数据的时候就直接存储到硬盘中,这样不会耗内存,数据也比较安全。示例代码以下:
from scrapy.exporters import JsonLinesItemExporter class QsbkPipeline(object): def __init__(self): self.fp = open('duanzi.json','wb') self.exporter = JsonLinesItemExporter(self.fp,ensure_ascii = False,encoding = 'utf-8') def open_spider(self,spider): print('爬虫开始了...') def process_item(self, item, spider): self.exporter.export_item(item) return item def close_spider(self,spider): self.fp.close() print('爬虫结束')
在上一个糗事百科的爬虫案例中。咱们是本身在解析完整个页面后获取下一页的url,而后从新发送一个请求。有时候咱们想要这样作,只要知足某个条件的url,都给我进行爬取。那么这时候咱们就能够经过CrawlSpider
来帮咱们完成了。CrawlSpider
继承自Spider
,只不过是在以前的基础之上增长了新的功能,能够定义爬取的url的规则,之后scrapy碰到知足条件的url都进行爬取,而不用手动的yield Request
。
3.1.1建立CrawlSpider爬虫
以前建立爬虫的方式是经过scrapy genspider [爬虫名字] [域名]
的方式建立的。若是想要建立CrawlSpider
爬虫,那么应该经过如下命令建立:
scrapy genspider -t crawl [爬虫名字] [域名]
3.1.2 LinkExtractors连接提取器
使用LinkExtractors
能够不用程序员本身提取想要的url,而后发送请求。这些工做均可以交给LinkExtractors
,他会在全部爬的页面中找到知足规则的url
,实现自动的爬取。如下对LinkExtractors
类作一个简单的介绍:
class scrapy.linkextractors.LinkExtractor( allow = (), deny = (), allow_domains = (), deny_domains = (), deny_extensions = None, restrict_xpaths = (), tags = ('a','area'), attrs = ('href'), canonicalize = True, unique = True, process_value = None )
主要参数讲解:
3.1.3 Rule规则类
定义爬虫的规则类。如下对这个类作一个简单的介绍:
class scrapy.spiders.Rule( link_extractor, callback = None, cb_kwargs = None, follow = None, process_links = None, process_request = None )
主要参数讲解:
LinkExtractor
对象,用于定义爬取规则。CrawlSpider
使用了parse
做为回调函数,所以不要覆盖parse
做为回调本身的回调函数。爬虫部分代码:
# -*- coding: utf-8 -*- import scrapy from scrapy.linkextractors import LinkExtractor from scrapy.spiders import CrawlSpider, Rule from wxapp.items import WxappItem class WxAppSpider(CrawlSpider): name = 'wx_app' allowed_domains = ['wxapp-union.com'] start_urls = ['http://www.wxapp-union.com/portal.php?mod=list&catid=2&page=1'] rules = ( Rule(LinkExtractor(allow=r'.+mod=list&catid=2&page=\d'), follow=True), Rule(LinkExtractor(allow=r'.+article-.+\.html'),callback="parse_detail",follow=False), ) def parse_detail(self, response): title = response.xpath('//h1[@class="ph"]/text()').get() author_p = response.xpath('//p[@class="authors"]') author = author_p.xpath('.//a/text()').get() pub_time = author_p.xpath('.//span/text()').get() content = response.xpath('//td[@id="article_content"]//text()').getall() content = ''.join(content).strip() item = WxappItem(title=title,author=author,pub_time=pub_time,content=content) #item['domain_id'] = response.xpath('//input[@id="sid"]/@value').get() #item['name'] = response.xpath('//div[@id="name"]').get() #item['description'] = response.xpath('//div[@id="description"]').get() yield item
items.py部分代码:
import scrapy class WxappItem(scrapy.Item): # define the fields for your item here like: # name = scrapy.Field() title = scrapy.Field() author = scrapy.Field() pub_time = scrapy.Field() content = scrapy.Field()
pipeline部分代码:
# -*- coding: utf-8 -*- # Define your item pipelines here # # Don't forget to add your pipeline to the ITEM_PIPELINES setting # See: https://doc.scrapy.org/en/latest/topics/item-pipeline.html from scrapy.exporters import JsonLinesItemExporter class WxappPipeline(object): def __init__(self): self.fp = open('wxjc.json','wb') self.exporter = JsonLinesItemExporter(self.fp,ensure_ascii = False,encoding = 'utf-8') def process_item(self, item, spider): self.exporter.export_item(item) return item def close_spider(self,spider): self.fp.close()
总结:
1. CrawlSpider使用"LinkExtractor"和Rule决定爬虫的具体走向。
2. LinkExtractor参数 allow设置规则:设置的url正则表达式要可以限制在咱们想要的url上
3. Rule参数follow的设置:若是在爬取页面的时候,须要将知足当前条件的url再进行跟进,那么设置为Ture,不然设置为False。
4.何时指定callback:若是这个url对应的页面,只是为了获取更多的url,并不须要里面的数据,那么能够不指定callback,若是想要获取url对应页面中的数据,那么就须要指定一个callback。
class Request(object_ref): def __init__(self, url, callback=None, method='GET', headers=None, body=None, cookies=None, meta=None, encoding='utf-8', priority=0, dont_filter=False, errback=None, flags=None): self._encoding = encoding # this one has to be set first self.method = str(method).upper() self._set_url(url) self._set_body(body) assert isinstance(priority, int), "Request priority not an integer: %r" % priority self.priority = priority if callback is not None and not callable(callback): raise TypeError('callback must be a callable, got %s' % type(callback).__name__) if errback is not None and not callable(errback): raise TypeError('errback must be a callable, got %s' % type(errback).__name__) assert callback or not errback, "Cannot use errback without a callback" self.callback = callback self.errback = errback self.cookies = cookies or {} self.headers = Headers(headers or {}, encoding=encoding) self.dont_filter = dont_filter self._meta = dict(meta) if meta else None self.flags = [] if flags is None else list(flags)
Request对象在咱们写爬虫爬取一页数据后须要从新发送一个请求的时候调用,这个类须要传递一些参数,其中比较经常使用的参数有:
1. url:这个是request对象发送请求的url
2. callback:在下载器下载完成相应的数据后执行回调函数
3. method:请求的方法,默认为GET方法,能够设置为其余方法
4. headers:请求头,对于一些固定的设置,放在settings.py中指定就能够,对于非固定的请求头,能够在发送请求的时候指定。
5. cookies (dict or list) :请求的cookies。能够被设置成以下两种形式。
request_with_cookies = Request(url="http://www.example.com", cookies={'currency': 'USD', 'country': 'UY'})
request_with_cookies = Request(url="http://www.example.com", cookies=[{'name': 'currency', 'value': 'USD', 'domain': 'example.com', 'path': '/currency'}])
6. meta:比较经常使用,用于在不一样的请求之间传递数据
7. encoding:编码,默认为utf-8
8. dot_filter:表示不禁调度器过滤,在执行屡次重复的请求的时候用的较多,设置为True,可避免重复发送相同的请求
9. errback:在发送错误的时候执行的函数
发送Post请求:
有时候咱们想要在请求数据的时候发送post请求,那么这时候须要使用Request的子类FormRequest来实现。若是想要在爬虫一开始的时候就发送Post请求,那么须要在爬虫类中重写start_requests(self)方法,而且再也不调用start_urls里的url.
Response对象通常由Scrapy自动构建,所以开发者不须要关心如何建立Response对象。Response对象有不少属性,经常使用属性以下:
1. meta:从其余请求传过来的meta属性,能够用来保持多个请求之间的数据链接
2. encoding:返回当前字符串编码和解码格式
3. text:将返回的数据做为unicode字符串返回
4. body:将返回的数据做为bytes字符串返回
5. xpath:xpath选择器
6. css:css选择器
4.3.1 模拟登陆人人网
爬虫部分代码:
# -*- coding: utf-8 -*- import scrapy class RenrenSpider(scrapy.Spider): name = 'renren' allowed_domains = ['renren.com'] start_urls = ['http://www.renren.com/'] def start_requests(self): # 在爬虫一开始发送Post请求,须要重写start_requests(self)方法 #发送post请求,推荐使用scrapy.FormRequest方法,能够指定表单数据 url = 'http://www.renren.com/PLogin.do' data = {'email':'970138074@qq.com','password':'pythonspider'} request = scrapy.FormRequest(url,formdata=data,callback=self.parse_page) yield request def parse_page(self,response): request = scrapy.Request(url = 'http://www.renren.com/443362311/profile', callback=self.parse_profile) yield request def parse_profile(self,response): with open('dp.html','w',encoding='utf-8') as fp: fp.write(response.text)
1) 经过本身写图片下载程序下载汽车之家宝马5系图片,示例以下:
爬虫部分代码:
# -*- coding: utf-8 -*- import scrapy from BM5X.items import Bm5XItem class Bm5xSpider(scrapy.Spider): name = 'bm5x' allowed_domains = ['https://car.autohome.com.cn/'] start_urls = ['https://car.autohome.com.cn/pic/series/65.html'] def parse(self, response): uniboxs = response.xpath("//div[@class='uibox']")[1:] for unibox in uniboxs: category = unibox.xpath(".//div[@class='uibox-title']/a/text()").get() urls = unibox.xpath(".//ul/li/a/img/@src").getall() urls = list(map(lambda url:response.urljoin(url),urls)) item = Bm5XItem(category=category,urls=urls) yield item
items.py部分代码:
import scrapy class Bm5XItem(scrapy.Item): # define the fields for your item here like: # name = scrapy.Field() category = scrapy.Field() urls = scrapy.Field()
pipeline部分代码:
import os from urllib import request class Bm5XPipeline(object): def __init__(self): BATH = os.path.dirname(os.path.dirname(__file__)) self.path = os.path.join(BATH,'images') if not os.path.exists(self.path): os.makedirs(self.path) def process_item(self, item, spider): category = item['category'] urls = item['urls'] category_path = os.path.join(self.path,category) if not os.path.exists(category_path): os.makedirs(category_path) for url in urls: image_name = url.split('_')[-1] request.urlretrieve(url,os.path.join(category_path,image_name)) return item
2) 使用scrapy 内置下载文件方法下载汽车之家宝马5系图片,示例以下:
Scrapy为下载item中包含的文件(好比在爬取到产品时,同时也想保存对应的图片)提供了一个可重用的item pipelines。这些pipelines有些共同的方法和结构(咱们称之为media pipeline)。通常来讲你会使用Files pipline 或者Images pipline。
为何要选择使用scrapy内置的下载文件的方法:
1) 避免从新下载最近已经下载过的数据
2) 能够方便的指定文件存储的路径
3) 能够将下载的图片转换为通用的格式,好比png或jpg
4) 能够方便的生成缩略图
5) 能够方便的检测图片的宽和高,确保他们知足最小的限制
6) 异步下载,效率很是高
下载文件的Files Pipeline:
当使用Files Pipline 下载文件的时候,按照如下步骤来完成:
1) 定义好一个Item,而后在这个item中定义两个属性,分别为file_urls以及files。file_urls是用来存储须要下载的文件的url连接,须要给一个列表。
2) 当文件下载完成后,会把文件下载的相关信息存储到item的files属性中,好比下载路径和文件校验码等。
3) 在配置文件setting.py中配置FILES_STORE,这个配置是用来设置文件下载下来的路径。
4) 启动pipline,在ITEM_PIPELINES中设置
ITEM_PIPELINES = {
# 'BM5X.pipelines.Bm5XPipeline': 300,
'scrapy.pipelines.files.FilesPipeline':1
}
下载图片的Images Pipeline:
当使用Images Pipline下载文件的时候,按照如下步骤来完成:
1) 定义好一个Item,而后在这个item中定义两个属性,分别为image_urls以及images。image_urls是用来存储须要下载的图片的url连接,须要给一个列表。
2) 当文件下载完成后,会把文件下载的相关信息存储到item的images属性中,以下下载路径,下载的url和图片的校验码等。
3) 在配置文件settings.py中配置IMAGES_STORE,这个配置是用来设置图片下载下来的路径。
4) 启动pipline ,在ITEM_PIPELINES中设置
ITEM_PIPELINES = {
# 'BM5X.pipelines.Bm5XPipeline': 300,
'scrapy.pipelines.images.ImagesPipeline':1
}
爬虫部分代码:
# -*- coding: utf-8 -*- import scrapy from BM5X.items import Bm5XItem class Bm5xSpider(scrapy.Spider): name = 'bm5x' allowed_domains = ['https://car.autohome.com.cn/'] start_urls = ['https://car.autohome.com.cn/pic/series/65.html'] def parse(self, response): uniboxs = response.xpath("//div[@class='uibox']")[1:] for unibox in uniboxs: category = unibox.xpath(".//div[@class='uibox-title']/a/text()").get() urls = unibox.xpath(".//ul/li/a/img/@src").getall() urls = list(map(lambda url:response.urljoin(url),urls)) item = Bm5XItem(category=category,image_urls=urls) yield item
items.py部分代码:
import scrapy class Bm5XItem(scrapy.Item): # define the fields for your item here like: # name = scrapy.Field() category = scrapy.Field() image_urls = scrapy.Field() images = scrapy.Field()
pipeline部分代码:
import os from scrapy.pipelines.images import ImagesPipeline from BM5X import settings class BM5XImagesPipeline(ImagesPipeline): def get_media_requests(self, item, info): #这个方法是在发送下载请求以前调用 #其实这个方法自己就是去发送下载请求的 request_objs = super(BM5XImagesPipeline,self).get_media_requests(item,info) for request_obj in request_objs: request_obj.item = item return request_objs def file_path(self, request, response=None, info=None): #这个方法是在图片将要被保存的时候调用,来获取这个图片存储的路径 path = super(BM5XImagesPipeline,self).file_path(request,response,info) category = request.item.get('category') images_store = settings.IMAGES_STORE category_path = os.path.join(images_store,category) if not os.path.exists(category_path): os.makedirs(category_path) image_name = path.replace('full/','') image_path = os.path.join(category_path,image_name) return image_path
setting部分代码:
# -*- coding: utf-8 -*- # Scrapy settings for BM5X project # # For simplicity, this file contains only settings considered important or # commonly used. You can find more settings consulting the documentation: # # https://doc.scrapy.org/en/latest/topics/settings.html # https://doc.scrapy.org/en/latest/topics/downloader-middleware.html # https://doc.scrapy.org/en/latest/topics/spider-middleware.html import os BOT_NAME = 'BM5X' SPIDER_MODULES = ['BM5X.spiders'] NEWSPIDER_MODULE = 'BM5X.spiders' # Crawl responsibly by identifying yourself (and your website) on the user-agent #USER_AGENT = 'BM5X (+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://doc.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/73.0.3683.103 Safari/537.36', } # Enable or disable spider middlewares # See https://doc.scrapy.org/en/latest/topics/spider-middleware.html #SPIDER_MIDDLEWARES = { # 'BM5X.middlewares.Bm5XSpiderMiddleware': 543, #} # Enable or disable downloader middlewares # See https://doc.scrapy.org/en/latest/topics/downloader-middleware.html #DOWNLOADER_MIDDLEWARES = { # 'BM5X.middlewares.Bm5XDownloaderMiddleware': 543, #} # Enable or disable extensions # See https://doc.scrapy.org/en/latest/topics/extensions.html #EXTENSIONS = { # 'scrapy.extensions.telnet.TelnetConsole': None, #} # Configure item pipelines # See https://doc.scrapy.org/en/latest/topics/item-pipeline.html ITEM_PIPELINES = { # 'BM5X.pipelines.Bm5XPipeline': 300, 'BM5X.pipelines.BM5XImagesPipeline':1 } # Enable and configure the AutoThrottle extension (disabled by default) # See https://doc.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://doc.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' #图片下载路径,供images pipline使用 IMAGES_STORE = os.path.join(os.path.dirname(os.path.dirname(__file__)),'images')
下载器中间件是引擎和下载器之间通讯的中间件。在这个中间件中咱们能够设置代理、更换请求头等来达到反反爬虫的目的。要写下载器中间件,能够在下载器中实现两个方法,一个是process_request(self,request,spider),这个方法是在请求发送以前执行,还有一个是process_response(self,request,response,spider),这个方法是数据下载到引擎以前执行。
process_request(self,request,spider):
这个方法是下载器在发送请求以前执行,通常能够在这个里面设置随机代理ip等。
1)参数:
request: 发送请求的request对象。
spider: 发送请求的spider对象。
2)返回值:
返回None:若是返回None,Scrapy将继续处理该request,执行其余中间件中的相应方法,直到合适的下载器处理函数被调用
返回Response对象:Scrapy 将不会调用任何其余的process_request方法,将直接返回这个response对象。已经激活的中间件process_response()方法则会在每一个response返回时被调用
返回Request对象:再也不使用以前的request对象去下载数据,而是根据如今返回的request对象返回数据。
若是这个方法中出现了异常,则会调用process_exception方法
process_response(self,request,response,spider):
这个是下载器下载数据到引擎过程当中执行的方法
1)参数:
request:request 对象
response:被处理的response对象
spider:spider对象
2)返回值:
返回Response对象:会将这个新的response对象传给其余中间件,最终传给爬虫
返回Request对象:下载器链被切断,返回的request会从新被下载器调度下载
若是抛出一个异常,那么调用request的errback方法,若是没有指定这个方法,那么会抛出一个异常
>>>>>>待续