前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >scrapy进阶开发(四):spiderMiddleware

scrapy进阶开发(四):spiderMiddleware

作者头像
Meet相识
发布2018-09-12 16:36:53
1.4K1
发布2018-09-12 16:36:53
举报
文章被收录于专栏:技术专栏技术专栏

SpiderMiddleWare的定义

spiderMiddleware 是一个Scrapy的spider处理机制的钩子框架,你可以插入自定义的功能用来处理engine发往spider的response和spider发往engine的request和item

激活SpiderMiddleware

想要激活SpiderMiddleware,需要在settings里配置SPIDER_MIDDLEWARES,这是一个字典dict,key:value对应的是 类路径:顺序,顺序由大到小,越小的越靠近spider,由大的越靠近engine,也就是说,由spider到engine是升序调用,从engine到spider为降序调用

代码语言:javascript
复制
SPIDER_MIDDLEWARES = {
    'myproject.middlewares.CustomSpiderMiddleware': 543,
    #如果想禁用一个内置的spider,需要将其顺序设置为None
    'scrapy.spidermiddlewares.offsite.OffsiteMiddleware': None,
}

定义自己的spider

代码语言:javascript
复制
class scrapy.spidermiddlewares.SpiderMiddleware:
    """ 
    这个方法在将response发往spider的过程中被调用
    这个方法应该返回None或者raise一个异常
    * response:正在响应的处理
    * spider:该响应的目标spider
    """
    def process_spider_input(response, spider):
        pass
        
    """
    这个方法将在requset或者item发往engine的过程中被调用
    这个方法必须返回一个reponse,dict,item
    * response:产生该响应对应的response
    * result:(一个request,dict,item)由这个spider返回的结果
    * spider:该响应的目标spider
    """
    def process_spider_output(response, result, spider):
        pass
        
    """
    这个方法将在一个spider或者一个process_spider_input方法抛出异常的时候被调用
    这个方法应该返回None或者一个reponse,dict,item
    * response :当前的相应
    * exception:抛出的异常
    * spider:当前的爬虫
    """    
    process_spider_exception(response, exception, spider):
        pass
    
    """
    这个方法用来处理首次发往engine的请求,和process_spider_output唯一不同的地方是,不接受response,并且只能返回一个request
    """
    process_start_requests(start_requests, spider):
        pass
        
        
    """
    如果这个方法存在,将用来创建一个middleware实例,并且应该将改实例返回,这个方法接收一个crawler对象,改对象提供了spider的所有核心配置
    这提供了一种方法让middleware可以访问其配置并hook住其他的scrapy组件
    """
    @classmethod    
    from_crawler(cls, crawler):
        pass

内置的SpiderMiddleware

scrapy内置的SpiderMiddleware 都在scrapy.spiderMiddlewares下面

image.png

看一下HttpErrorMiddleware的源码

代码语言:javascript
复制
class HttpErrorMiddleware(object):

    @classmethod
    def from_crawler(cls, crawler):
        """
        这个方法将settings传给构造函数,并返回了创建的实例
        """
        return cls(crawler.settings)

    def __init__(self, settings):
        """
        构造函数
        """
        # 获取HTTPERROR_ALLOW_ALL配置,改配置是一个布尔类型,声明是否需要spider自己处理所有的http相应状态码
        self.handle_httpstatus_all = settings.getbool('HTTPERROR_ALLOW_ALL')
        # 获取HTTPERROR_ALLOWED_CODES配合,该配置是一个list,声明spider需要自己处理的http响应状态码
        self.handle_httpstatus_list = settings.getlist('HTTPERROR_ALLOWED_CODES')

    def process_spider_input(self, response, spider):
        """
        处理发往spider的相应
        """
        # 如果是200-300之间的状态码,之间返回由spider处理
        if 200 <= response.status < 300:  # common case
            return
        # 获取元信息 
        meta = response.meta
        
        # 如果在元信息里包含handle_httpstatus_all这个参数,
        # 则说明当前请求相应的所有状态码都需要自己处理,直接返回
        if 'handle_httpstatus_all' in meta:
            return
            
        # 同上,只不过这里变成了list    
        if 'handle_httpstatus_list' in meta:
            allowed_statuses = meta['handle_httpstatus_list']
            
        # 如果配置里声明了需要处理所有的请求,则直接返回    
        elif self.handle_httpstatus_all:
            return
        else:
        # 如果上面条件全都不满足,则获取当前spider的handle_httpstatus_list属性
            allowed_statuses = getattr(spider, 'handle_httpstatus_list', self.handle_httpstatus_list)
        
        # 如果当前的status在运行自己处理的status列表里,则直接返回
        if response.status in allowed_statuses:
            return
        
        # 如果上面都没有满足,则说明当前status需要由scrapy框架处理,所以抛出一个异常
        raise HttpError(response, 'Ignoring non-200 response')


    def process_spider_exception(self, response, exception, spider):
        """
        处理HttpError的异常
        """
        # 只处理HttpError的异常
        if isinstance(exception, HttpError):
            # 当前异常状态码出现次数加1
            spider.crawler.stats.inc_value('httperror/response_ignored_count')
            spider.crawler.stats.inc_value(
                'httperror/response_ignored_status_count/%s' % response.status
            )
            打印日志
            logger.info(
                "Ignoring response %(response)r: HTTP status code is not handled or not allowed",
                {'response': response}, extra={'spider': spider},
            )
            return []
本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
原始发表:2018.03.04 ,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • SpiderMiddleWare的定义
  • 激活SpiderMiddleware
  • 定义自己的spider
  • 内置的SpiderMiddleware
    • scrapy内置的SpiderMiddleware 都在scrapy.spiderMiddlewares下面
    领券
    问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档