理解Scrapy中的回调函数

12 投票
3 回答
20767 浏览
提问于 2025-04-17 23:54

我刚开始学习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这一行是在response.meta之前执行的吗?在parse_page2里?
  3. parse_page2返回的item去哪了?
  4. parse_page1里,return request这一句有什么用?我以为提取的项目应该在这里返回。

3 个回答

1

scrapy: 理解回调之间的项目和请求是如何工作的这个问题中,eLRuLL的回答非常精彩。

我想补充一下关于项目转换的部分。首先,我们要明确,回调函数只在这个请求的响应下载完成后才会工作。

在scrapy文档给出的代码中,并没有声明页面1的URL和请求。我们假设页面1的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)

当页面1的响应下载完成后,parse_page1会被调用来生成页面2的请求:

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

在页面2的响应下载完成后,parse_page2会被调用来返回一个项目:

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.
1
  1. 没错,Scrapy使用了一种叫做扭曲反应器的东西来调用爬虫函数,这样就能确保只用一个循环和一个线程来处理事情。
  2. 爬虫函数调用者希望能得到一些数据项或者请求的结果,请求会被放进一个队列,等着以后处理,而数据项则会被发送到配置好的处理管道里。
  3. 把一个数据项(或者其他数据)保存在请求的元数据里,只有在后续处理响应时需要用到的时候才有意义,否则直接从parse_page1返回数据会更好,这样就不用多发一次HTTP请求了。
20

阅读一下文档

对于爬虫来说,抓取的过程大致是这样的:

  1. 首先,你会生成初始的请求,去爬取第一个网址,并指定一个回调函数,这个函数会在下载完请求的响应后被调用。

    最开始的请求是通过调用start_requests()方法获得的,默认情况下,这个方法会为start_urls中指定的网址生成Request,并将parse方法作为请求的回调函数。

  2. 在回调函数中,你会解析响应(网页),并返回Item对象、Request对象,或者两者的可迭代对象。这些请求也会包含一个回调(可能是同一个),然后Scrapy会下载这些请求的响应,并由指定的回调来处理。

  3. 在回调函数中,你会解析页面内容,通常使用选择器(当然你也可以用BeautifulSoup、lxml或者你喜欢的其他工具),并根据解析的数据生成项目。

  4. 最后,从爬虫返回的项目通常会被保存到数据库中(在某个项目管道中),或者使用数据导出写入文件。

回答:

parse_page2中,'item'是怎么填充的?request.meta这一行是在response.meta之前执行的吗?

爬虫是由Scrapy引擎管理的。它首先从start_urls中指定的网址发起请求,并将这些请求传递给下载器。当下载完成后,请求中指定的回调会被调用。如果回调返回另一个请求,就会重复这个过程。如果回调返回一个Item,这个项目会被传递到一个管道中以保存抓取的数据。

parse_page2返回的项目去哪了?

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

根据文档说明,每个回调(parse_page1parse_page2)可以返回一个Request或一个Item(或者它们的可迭代对象)。parse_page1返回的是Request而不是Item,因为还需要从其他网址抓取额外的信息。第二个回调parse_page2返回的是一个项目,因为所有信息都已经抓取完毕,可以传递给管道了。

撰写回答