Scrapy提供扩展(扩展是正常的python类,它们会在Scrapy启动时被实例化、初始化)机制,让人能将自定义功能绑定到Scrapy中。
1、Scrapy中的内置扩展设置EXTENSIONS_BASE
扩展在扩展类被实例化时加载和激活,实例化代码必须在类的构造函数(__init__)中执行。
(1)'scrapy.extensions.corestats.CoreStats':0
名称:核心统计扩展
说明:如果统计收集器(stats collection)启用了,该扩展开启核心统计收集
(2)'scrapy.telnet.TelnetConsole':0
名称:Telnet控制台扩展
说明:提供了一个telnet控制台,telnet控制台通过TELNETCONSOLE_ENABLED配置项开启,服务器会监听TELNETCONSOLE_PORT指定的端口
(3)'scrapy.extensions.memusage.MemoryUsage':0
名称:内存使用扩展
说明:监听Scrapy进程内存使用量,如果使用内存量超过某个指定值,发送提醒邮件,如果超过某个指定值,关闭spider
(4)'scrapy.extensions.memdebug.MemoryDebugger':0
名称:内存调试扩展
说明:该扩展用于调试内存使用量,开启该扩展,需要打开MEMDEBUG_ENABLED配置项
(5)'scrapy.extensions.closespider.CloseSpider':0
名称:当某些状况发生,spider会自动关闭,用来为状况指定关闭方式
(6)'scrapy.extensions.feedexport.FeedExporter':0
(7)'scrapy.extensions.logstats.LogStats':0
名称:记录统计扩展
说明:记录基本的统计信息,比如爬取的页面和条目(items)
(8)‘scrapy.extensions.spiderstate.SpiderState’:0
(9)‘scrapy.extensions.throttle.AutoThrottle’:0
(10)‘scrapy.extensions.statsmailer.StatsMailer’:0
名称:StatsMailer扩展
说明:这个简单的扩展可用来在一个域名爬取完毕时发送提醒邮件,包含Scrapy收集的统计信息。邮件会发送给通过STATSMAILER_RCPTS指定的所有接收人
扩展一般分为三种状态:可用的(Available)、开启的(enabled)和禁用的(disabled)。一些扩展经常需要依赖一些特别的配置,比如HTTP Cache扩展是可用的但默认是禁用的,除非设置了HTTPCACHE_ENABLED配置项。通过将其顺序设置为None,即可禁用。
2、定制扩展
扩展类是一个Python类,如果想操作Scrapy的功能,需要一个入口:from_crawler类方法,它接收一个Crawler类的实例,通过这个对象可以访问settings(设置)、signals(信号)、stats(状态),以便控制爬虫的行为。
2.1 Scrapy提供的异常及其用法
(1)DropItem异常
原型:scrapy.exceptions.DropItem
说明:该异常由item pipeline抛出,用于停止处理item
(2)CloseSpider异常
原型:scrapy.exceptions.CloseSpider(reason='cancelled')
说明:该异常由spider的回调函数(callback)抛出,来停止/暂停spider。支持的参数:reason(str):关闭的原因
(3)IgnoreRequest异常
原型:scrapy.exceptions.IgnoreRequest
说明:该异常由调度器(scheduler)或其他下载器中间件抛出,声明忽略该request
(4)NotConfigured异常
原型:scrapy.exceptions.NotConfigured
说明:该异常由某些组件抛出,申明其仍然保持关闭。这些组件包括:Extensions、Item pipelines、Downloader middlwares、Spider middlewares。该异常必须由组件的构造器(constructor)抛出。
(5)NotSupported异常
原型:scrapy.exceptions.NotSupported
说明:该异常申明一个不支持的特性
2.2 Scrapy内置的信号
(1)engine_started
原型:scrapy.signals.engine_started()
说明:当Scrapy引擎启动爬取时发送该信号,该信号支持返回deferreds
(2)engine_stopped
原型:scrapy.signals.engine_stopped()
说明:当Scrapy引擎停止时发送该信号,例如爬取结束,该信号支持返回deferreds
(3)item_scraped
原型:scrapy.signals.item_scraped(item,response,spider)
参数:item(dict或Item对象):爬取到的item
spider(Spider对象):爬取item的spider
response(Response对象):提取item的response
说明:当item被爬取,并通过所有Item Pipeline后(没有被丢弃dropped),发送该信号。该信号支持返回deferreds
(4)item_dropped
原型:scrapy.signals.item_dropped(item,exception,spider)
参数:item(dict或Item对象):Item Pipeline丢弃的item
spider(Spider对象):爬取item的spider
exception(DropItem异常):导致item被丢弃的异常
说明:当item通过Item Pipeline,有些pipeline抛出DropItem异常,丢弃Item时,该信号被发送。该信号支持返回deferreds
(5) spider_closed
原型:scrapy.signals.spider_closed(spider,reason)
参数:spider(Spider对象):关闭的spider
reason(str):描述Spider被关闭的原因的字符串。如果Spider是由于完成爬取而被关闭,则其为”finished“。否则,如果Spider是被引擎的close_spider方法所关闭,则其为调用该方法时传入的reason参数(默认为”cancelled“)。如果引擎被关闭(如输入ctrl+c),则其为shutdown
说明:当某个Spider被关闭时,该信号被发送,该信号可以用来释放每个Spider在spider_opened时占用的资源。该信号支持返回deferreds
(6)spider_opened
原型:scrapy.signals.spider_opened(spider)
参数:spider(Spider对象):开启的spider
说明:当spider开始爬取时发送该信号,该信号一般用来分配Spider的资源,不过它也能做任何事情。该信号支持返回deferreds
(7)spider_idle
原型:scrapy.signals.spider_idle(spider)
参数:spider(Spider对象):空闲的Spider
说明:当Spider进入空闲(idle)状态时该信号被发送。空闲说明:1)Requests正在等待被下载。2)Request被调度。3)Items正在Item Pipeline中被处理
当该信号的所有处理器(handler)被调用后,如果spider仍然保持空闲状态,引擎将会关闭该spider。当spider被关闭后,spider_closed信号将被发送,可以在spider_idle处理器中调度某些请求来避免spider被关闭。
该信号不支持返回deferreds
(8)spider_error
原型:scrapy.signals.spider_error(failure,response,spider)
参数:failure(Failure对象):以Twisted Failure对象抛出的异常
response(Response对象):当异常被抛出时被处理的response
spider(Spider对象):抛出异常的Spider
说明:当Spider的回调函数产生错误时,例如抛出异常,该信号被发送
(9)request_scheduled
原型:scrapy.signals.request_scheduled(request,spider)
参数:request(Request对象):到达调度器的Request
spider(Spider对象):产生该Request的Spider
说明:当引擎调度一个Request对象用于下载时,该信号被发送,该信号不支持返回deferreds
(10)response_received
原型:scrapy.signals.response_received(response,request,spider)
参数:response(Request对象):接收到的resposne
request(Request对象):生成response的request
spider(Spider对象):response所对应的spider
说明:当引擎从downloader获取到一个新的Response时发送该信号,该信号不支持返回deferreds
(11)response_downloaded
原型:scrapy.signals.response_downloaded(response,request,spider)
参数:response(Response对象):下载的response
request(Request对象):生成的response的request
spider(Spider对象):response所对应的 spider
说明:当一个HTTPResponse被下载时,由downloader发送该信号,该信号不支持返回deferreds
2.3 扩展代码
代码来自:《Python爬虫开发与项目实战》范传辉著
扩展需要关联到signals并执行它们触发的任务,如果from_crawler()方法抛出NotConfigured异常,扩展会被禁用,否则,扩展会被开启。
import logging from scrapy import signals from scrapy import crawler from scrapy.exceptions import NotConfigured logger = logging.getLogger(__name__) class SpiderOpenCloseLogging(object): """当出现(spider被打开,spider被关闭,爬取了特定数量的Item)事件时,记录一条日志""" def __init__(self,item_count): self.item_count = item_count self.items_scraped = 0 @classmethod def from_crawler(cls, crawler): # 首先检查一下是否存在响应的配置,如果不存在则抛出NotConfigured异常 if not crawler.settings.getbool("MYEXT_ENABLED"): raise NotConfigured # 从setting中获取MYEXT_ITEMCOUNT的值 item_count = crawler.settings.getint("MYEXT_ITEMCOUNT",1000) # 初始化扩展实例 ext = cls(item_count) # 将扩展中的spider_opened、spider_closed和item_scraped连接到相应信号处,进行触发 crawler.signals.connect(ext.spider_opened,signal=signals.spider_opened) crawler.signals.connect(ext.spider_closed, signal=signals.spider_closed) crawler.signals.connect(ext.item_scraped, signal=signals.item_scraped) # 扩展实例返回 return ext def spider_opened(self,spider): logger.info("opened spiders %s",spider.name) def spider_closed(self,spider): logger.info("closed spiders %s",spider.name) def item_scraped(self,item,spider): self.items_scraped += 1 if self.items_scraped % self.item_count == 0: logger.info("scraped %d items", self.items_scraped)