理解Scrapy中的回调函数
我刚开始学习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
我有一些地方不太明白:
item
是怎么填充的?request.meta
这一行是在response.meta
之前执行的吗?在parse_page2
里?- 从
parse_page2
返回的item
去哪了? - 在
parse_page1
里,return request
这一句有什么用?我以为提取的项目应该在这里返回。
3 个回答
在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.
- 没错,Scrapy使用了一种叫做扭曲反应器的东西来调用爬虫函数,这样就能确保只用一个循环和一个线程来处理事情。
- 爬虫函数调用者希望能得到一些数据项或者请求的结果,请求会被放进一个队列,等着以后处理,而数据项则会被发送到配置好的处理管道里。
- 把一个数据项(或者其他数据)保存在请求的元数据里,只有在后续处理响应时需要用到的时候才有意义,否则直接从
parse_page1
返回数据会更好,这样就不用多发一次HTTP请求了。
阅读一下文档:
对于爬虫来说,抓取的过程大致是这样的:
首先,你会生成初始的请求,去爬取第一个网址,并指定一个回调函数,这个函数会在下载完请求的响应后被调用。
最开始的请求是通过调用
start_requests()
方法获得的,默认情况下,这个方法会为start_urls
中指定的网址生成Request
,并将parse
方法作为请求的回调函数。在回调函数中,你会解析响应(网页),并返回
Item
对象、Request
对象,或者两者的可迭代对象。这些请求也会包含一个回调(可能是同一个),然后Scrapy会下载这些请求的响应,并由指定的回调来处理。在回调函数中,你会解析页面内容,通常使用选择器(当然你也可以用BeautifulSoup、lxml或者你喜欢的其他工具),并根据解析的数据生成项目。
最后,从爬虫返回的项目通常会被保存到数据库中(在某个项目管道中),或者使用数据导出写入文件。
回答:
在
parse_page2
中,'item'
是怎么填充的?request.meta
这一行是在response.meta
之前执行的吗?
爬虫是由Scrapy引擎管理的。它首先从start_urls
中指定的网址发起请求,并将这些请求传递给下载器。当下载完成后,请求中指定的回调会被调用。如果回调返回另一个请求,就会重复这个过程。如果回调返回一个Item
,这个项目会被传递到一个管道中以保存抓取的数据。
从
parse_page2
返回的项目去哪了?在
parse_page1
中,return request
语句有什么用?我以为提取的项目需要从这里返回?
根据文档说明,每个回调(parse_page1
和parse_page2
)可以返回一个Request
或一个Item
(或者它们的可迭代对象)。parse_page1
返回的是Request
而不是Item
,因为还需要从其他网址抓取额外的信息。第二个回调parse_page2
返回的是一个项目,因为所有信息都已经抓取完毕,可以传递给管道了。