scrapy的架构
- ScrapyEngine(引擎):控制数据在框架之间的流动,并在动作发生时触发对应的动作。
- Schedule(调度器):接收引擎发送过来的url请求,并写入队列,会自动删除重复的url。
- Downloader(下载器):负责获取网页数据信息,并传递给引擎。
- Spider(爬虫):编写解析网页的方法,获取item和子链接并将url传给引擎。
- ItemPipline(管道):接收item,并按照设置好的内容进行处理。
除去以上五大基本构成之外,scrapy还有两个中间件:
- 下载中间件:在引擎和下载器之间,处理他们之间传递的请求和响应,可以通过设置此中间件,添加ip代理、cookie、UA等.
- spider中间件:在引擎和spider之间,处理爬虫的输入和输出。
scrapy的运行原理
运行图解
文字描述
- spider向引擎传入初始url
- 引擎将初始url传递给调度器,调度器将url写入队列中
- 调度器将处理好的requests请求返回给引擎
- 引擎将得到的requests请求再次传递给下载器,下载器根据事先设置好的下载中间件访问网页进行获取数据。如果下载失败,下载器回记录后重新访问。
- 下载器获得响应数据后,将response传回引擎
- 引擎将response传递给spider进行处理,spider默认为def parse()函数处理。
- spider处理完数据之后获得item和新的url,将这些再次传递给引擎。
- 引擎将item传递到管道中,将新获得的url传递给调度器,重复步骤2之后的操作,直到获得全部信息。
- 当调度器中的请求为空,程序才会停止
scrapy的目录
- 同名目录:
- spiders目录:# 爬虫文件目录
- —init—.py
- FirstProject.py # 爬虫文件
- items.py:# 自定义数据结构
- middlewares.py:# 中间件配置文件
- 管理下载中间件和爬虫中间件
- piplines.py:# 管道配置文件
- 编写得到item数据之后对数据的处理和导入
- settings.py:# 全局配置文件
- 设置日记、管道优先级等基本配置
- spiders目录:# 爬虫文件目录
- scrapy.cfg:项目基本配置文件
scrapy中间件
具体说明参照:scrpay中间件用法简介
spider中间件的使用频率小于下载中间件的使用频率。
spider中间件:
作用
在spider向引擎发送request之前,对request进行处理;
当引擎将返回的response,再次发送到spider之前,对response进行处理;
当spider获得item并要传输给管道之前,对item进行处理
详细框架如下
class DemoSpiderMiddleware:
@classmethod
def from_crawler(cls, crawler):
s = cls()
crawler.signals.connect(s.spider_opened, signal=signals.spider_opened)
return s
# 当response被中间件处理时,调用这个方法
def process_spider_input(self, response, spider):
# 如果返回None,则继续处理该response;
# 如果抛出异常,调用Request的errback(),
# 重新输入中间件中使用 process_spider_output()方法,
#如果该方法抛出异常则调用process_spider_exception()
return None
# 当spider处理response并返回结果(item或request)后调用该方法
def process_spider_output(self, response, result, spider):
# result为item或request的可迭代对象
# 如果该方法抛出异常则交由process_spider_exception()方法处理
for i in result:
yield i
def process_spider_exception(self, response, exception, spider):
pass
# spider启动request时被调用
def process_start_requests(self, start_requests, spider):
# 传入可迭代对象
for r in start_requests:
yield r
下载中间件
作用
- 在引擎向下载器传送request之前,对request进行修改;
1.1 例如修改请求头、设置代理、cookie等设置都可以通过它来实现。 - 在下载器生成response之后,通过引擎传输到spide之前,对响应内容 进行修改。
代码框架
class DemoDownloaderMiddleware:
@classmethod
def from_crawler(cls, crawler):
s = cls()
crawler.signals.connect(s.spider_opened, signal=signals.spider_opened)
return s
# request在被引擎发送给下载器之前,被调用
def process_request(self, request, spider):
return None
# 在response发送到spider处理之前被调用
def process_response(self, request, response, spider):
return response
# 对异常进行处理
def process_exception(self, request, exception, spider):
pass
def spider_opened(self, spider):
spider.logger.info('Spider opened: %s' % spider.name)
重点方法说明
process_request(self, request, spider)
- 如果抛出异常,则使用Request的errback()回调,如果异常没有被处理,那么就会忽略,如果有异常调用process_exception()方法。
- 如果返回None,继续处理该request,根据设置好的优先级依次对request进行处理,最后发送到下载器执行,直到下载器执行request后得到response后结束。
- 如果返回response对象,则更低优先级的process_request()和process_exception()将不再被调用,而是调用下载器中的process_response()方法,随后直接将response对象传递到spider中进行处理。
- 如果返回的是request对象,那么将不再继续调用更低优先级的process_request()方法,而是将这个对象重新放入队列中等待再一次被调度器调度,之后再次使用该方法进行处理。
process_response(self, request, response, spider)
- 如果返回的是response对象,更低优先级的process_response()将被继续调用,继续对响应对象进行处理
- 如果返回的是request对象,会将该对象重新放到队列中等待被process_request()方法再次调度。
- 如果抛出异常,则使用Request的errback()回调,如果异常没有被处理,那么就会忽略,如果有异常调用process_exception()方法
Request errback()方法:
默认情况下,响应状态在200-300之间是,调用callback对应的回调函数,而其他状态码则会调用errback对应的回调函数。
在setting.py文件中可以设置允许进入callback的非正常状态码的范围HTTPERROR_ALLOWED_CODES
,被设置在范围内的非正常状态码也会调用callback的回调函数,而不再执行errback。
如果调用的errback的回调函数,那么此时response.url是初始的url,而不是重定向的url。
我目前在中间件中的使用不多。我可以不用,但我不能不懂!!