• scrapy的Pipeline类不可使用yield


    scrapy的Pipeline类不可使用yield

    业务需求在scarpy的pipeline中处理过数据后再生成新的Request。但如果直接再Pipeline类的process_item方法中yield Request,会导致爬虫执行直接跳过该Pipeline,连个报错都看不到。

    排查发现是yield使该函数的调用的返回值成为生成器,而不是相关返回值。

    如何在Pipeline中生成新请求

    1.参照MediaPipeline。

    之所以我会先入为主地认为可以在Pipeline中直接yield出新Request,是因为之前使用过官方自带的MediaPipeline,改写其get_media_requests的方法,并可最终yield出新Request。

    则仿照MediaPipeline的process_item完成业务逻辑即可。

    MediaPipeline的process_item的主要逻辑如下

        def process_item(self, item, spider):
            info = self.spiderinfo
            requests = arg_to_iter(self.get_media_requests(item, info))
            dlist = [self._process_request(r, info) for r in requests]
            dfd = DeferredList(dlist, consumeErrors=1)
            return dfd.addCallback(self.item_completed, item, info)
    

    可看出是调用了twisted的DeferredList来分发请求。

    2.显式调用crawler.engine.crawl()

    该方法参考scrapy在pipeline中重新生成request

    显式调用crawler.engine.crawl(),将新的request发送至执行引擎。

    class MyPipeline(object):
    
        def __init__(self, crawler):
            self.crawler = crawler
    
        @classmethod
        def from_crawler(cls, crawler):
            return cls(crawler)
    
        def process_item(self, item, spider):
            ...
            self.crawler.engine.crawl(
                        Request(
                            url='someurl',
                            callback=self.custom_callback,
                        ),
                        spider,
                    )
    
        # YES, you can define a method callback inside the same pipeline
        def custom_callback(self, response):
            ...
            yield item
    
  • 相关阅读:
    解决PyQt5在安装后无法找到Designer.exe问题,两个位置可供参考
    观察者模式
    策略模式
    模板方法模式(下)
    学过的技术容易忘,怎么办?
    Mysql主从配置
    Springboot处理CORS跨域请求
    SpringBoot学习2之注解简单配置Springboot+MyBatis
    Confluence7.4安装并破解汉化教程
    mysql json类型
  • 原文地址:https://www.cnblogs.com/lymmurrain/p/15835461.html
Copyright © 2020-2023  润新知