代码之家  ›  专栏  ›  技术社区  ›  Homunculus Reticulli

scrapy回调函数是否可以指向生成请求的同一个函数

  •  0
  • Homunculus Reticulli  · 技术社区  · 7 年前

    我在用scrapy抓取一个站点。

    我有类似的代码:

    class mySpider(scrapy.Spider):
        def start_requests(self):
            yield SplashRequest(url=example_url,  
                                    callback=self.parse,
                                    cookies={'store_language':'en'},
                                    endpoint='render.html',
                                    args={'wait': 5}, 
                                )  
    
        def parse(self, response):
            try:
                self.extract_data_from_page(response)
    
                if (next_link_still_on_page(response):
                    next_url = grok_next_url(response)
    
                    yield SplashRequest(url=next_url, 
                                    callback=self.parse,
                                    cookies={'store_language':'en'},
                                    endpoint='render.html',
                                    args={'wait': 5}, 
                                )  
    
            except Exception:
                pass
    
    
        def extract_data_from_page(self, response):
            pass
    
    
        def next_link_still_on_page(self,response):
            pass
    
    
        def grok_next_url(self, response):
            pass
    

    parse() 方法,回调函数是 PARSE() 这是不应该的吗(例如,导致潜在堆栈溢出的逻辑错误?).

    0 回复  |  直到 7 年前
        1
  •  0
  •   malberts    7 年前

    可以 使用相同的回调。从技术角度来看,这不是问题。特别是如果产生的请求与当前请求具有相同的性质,那么它应该理想地重用相同的逻辑。

    但是,来自 必须阅读源代码的人 透视图,最好为 不同的 任务或页面类型(整个单一责任原则)。


    让我举个例子来说明。假设您有一个列表网站(jobs,products,whatever),您有两类主要的url:

    • 搜索结果页: .../search?q=something&page=2
    • 项目页: .../item/abc

    搜索结果页包含 分页链接 项目 . 这样的页面将产生两种请求:

    1. 分析下一页
    2. 分析项目

    项目页将不会生成另一个请求。

    所以现在你 可以 将所有这些填充到同一个解析器中,并将其用于每个请求:

    def parse(self, response):
        if 'search' in response.url:
            for item in response.css('.item'):
                # ...
                yield Request(item_url, callback=self.parse)
    
            # ...
            yield Request(next_url, callback=self.parse)
    
        if 'item' in response.url:
            yield {
                'title': response.css('...'),
                # ...
            }
    

    这显然是一个非常简洁的例子,但随着它的发展,将变得更难遵循。

    相反,请分解不同的页面分析器:

    def parse_search(self, response):
        for item in response.css('.items'):
            yield Request(item_url, callback=self.parse_item)
    
        next_url = response.css('...').get()
        yield Request(next_url, callback=self.parse_search)
    
    
    def parse_item(self, response):
        yield {
            'title': response.css('...'),
            # ...
        }
    

    所以基本上,如果是“另一个相同类型的页面”的问题,那么为了重用相同的逻辑,使用相同的回调是正常的。如果下一个请求需要不同类型的解析,则应创建一个单独的解析器。