【问题标题】:Understanding callbacks in Scrapy了解 Scrapy 中的回调
【发布时间】:2014-05-04 02:47:10
【问题描述】:

我是 Python 和 Scrapy 的新手。我以前没有使用过回调函数。但是,我现在为下面的代码做。将执行第一个请求,并将其响应发送到定义为第二个参数的回调函数:

def parse_page1(self, response):
    item = MyItem()
    item['main_url'] = response.url
    request = Request("http://www.example.com/some_page.html",
                      callback=self.parse_page2)
    request.meta['item'] = item
    return request

def parse_page2(self, response):
    item = response.meta['item']
    item['other_url'] = response.url
    return item

我无法理解以下内容:

  1. item 是如何填充的?
  2. request.meta 行是否在parse_page2 中的response.meta 行之前执行?
  3. parse_page2返回的item去哪了?
  4. parse_page1 中的return request 语句需要什么?我认为提取的项目需要从这里返回。

【问题讨论】:

    标签: python callback scrapy


    【解决方案1】:

    阅读docs

    对于蜘蛛,抓取周期是这样的:

    1. 您首先生成初始请求以抓取第一个 URL,并指定要与响应一起调用的回调函数 从这些请求中下载。

      首先要执行的请求是通过调用 start_requests() 方法(默认情况下)为 在 start_urlsparse 方法中指定的 URL 作为回调 请求函数。

    2. 在回调函数中,您解析响应(网页)并返回 Item 对象、Request 对象或两者的可迭代对象。 这些请求还将包含一个回调(可能相同)并将 然后被 Scrapy 下载,然后他们的响应由 指定回调。

    3. 在回调函数中,您解析页面内容,通常使用 Selectors(但您也可以使用 BeautifulSoup、lxml 或其他 您喜欢的机制)并使用解析的数据生成项目。

    4. 最后,从蜘蛛返回的项目通常会被持久化到数据库(在某些项目管道中)或写入文件 使用 Feed 导出

    答案:

    'item' 是如何填充的 request.meta 行在parse_page2 中的response.meta 行之前执行吗?

    蜘蛛由 Scrapy 引擎管理。它首先从start_urls 中指定的 URL 发出请求并将它们传递给下载器。下载完成时调用请求中指定的回调。如果回调返回另一个请求,则重复相同的事情。如果回调返回Item,则该项目被传递到管道以保存抓取的数据。

    parse_page2返回的商品去哪了?

    parse_page1 中的return request 语句需要什么?我认为提取的项目需要从这里返回?

    如文档中所述,每个回调(parse_page1parse_page2)都可以返回 RequestItem(或其中的一个可迭代对象)。 parse_page1 返回 Request 而不是 Item,因为需要从其他 URL 中抓取其他信息。第二个回调parse_page2 返回一个项目,因为所有信息都被抓取并准备好传递给管道。

    【讨论】:

    • 我已经阅读了这部分...但是我对控件在我提到的代码中的流动方式感到困惑..
    • 感谢您的解释...现在,当我再次阅读完整的内容时,这很有意义
    • 好的..我会这样做...我有一些理解如果我错了请纠正我-正如您所说的回调函数可以返回发送到队列进行处理的请求...所以在 parse_page1 中返回请求对象......所以此时(当 parse_page1 结束时)回调函数 parse_page2 被调用
    • 不,parse_page2 在下载请求的响应时被调用。这是异步的。同时,之前的请求可以在parse_page2 中完成下载被调用以获取另一个响应。
    • 好的...抱歉混淆...我想说的是,当 parse_page1 结束时..此时对返回的请求对象执行请求,并在下载响应时调用回调函数 parse_page2 .
    【解决方案2】:
    1. 是的,scrapy 使用a twisted reactor 调用蜘蛛函数,因此使用单线程的单循环可确保
    2. 蜘蛛函数调用者期望获得 item/s 或 request/s 作为回报,请求被放入队列中以供将来处理,并将项目发送到配置的管道
    3. 在请求元数据中保存一个项目(或任何其他数据)只有在收到响应后需要进一步处理时才有意义,否则显然最好从parse_page1返回它并避免额外的http请求调用

    【讨论】:

    • 感谢您的精彩解释...但是我对第三个问题仍然感到困惑...我想我没有解释清楚。那么,我想问的是,parse_page1 中的请求实例返回到哪里呢?为什么需要返回请求 - 控制到达此语句时是否调用回调函数?另外,我可以以与此处相同的方式传递项目列表并从 parse_page2 返回列表吗?
    【解决方案3】:

    scrapy: understanding how do items and requests work between callbacks ,eLRuLL的回答很精彩。

    我想添加项目变换的部分。首先,我们要清楚,回调函数只在这个请求的响应被加载之前才起作用。

    在scrapy.doc给出的代码中,它没有声明page1的url和请求。让我们将page1的url设置为“http://www.example.com.html”。

    [parse_page1] 是

    的回调
    scrapy.Request("http://www.example.com.html",callback=parse_page1)`
    

    [parse_page2] 是

    的回调
    scrapy.Request("http://www.example.com/some_page.html",callback=parse_page2)
    

    page1的response被下载后,调用parse_page1生成page2的请求:

    item['main_url'] = response.url # send "http://www.example.com.html" to item
    request = scrapy.Request("http://www.example.com/some_page.html",
                             callback=self.parse_page2)
    request.meta['item'] = item  # store item in request.meta
    

    page2的response下载完成后,调用parse_page2返回一个item:

    item = response.meta['item'] 
    #response.meta is equal to request.meta,so here item['main_url'] 
    #="http://www.example.com.html".
    
    item['other_url'] = response.url # response.url ="http://www.example.com/some_page.html"
    
    return item #finally,we get the item recording  urls of page1 and page2.
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2022-01-24
      • 2016-12-22
      • 1970-01-01
      • 2016-02-08
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-11-15
      相关资源
      最近更新 更多