scrapy框架中向回调函数传值的两个方法
在填充item时, 有时会先在一个parser取得部分数据, 然后在另一个parser里再取得另一部分数据. 这就涉及到了在两个parser间传递参数的问题.
可以先在第一个parser里取得数据, 然后把数据做为参数传递给第二个parser,在第二个parse里实例化Item.然后把所有数据都写入这个item实例.
也可以在第一个parser里实例化Item,然后填充这个item实例. 再把item实例作为参数传递给第二个parser. 这里主要是把item做为参数传递.
由于在调用第二个parser时,往往都是通过回调函数来使用的,这就涉及到了给回调函数传参的问题.
有两种方法,:
第一种是通用方法,用匿名函数,所有回调函数都可以用这种方法进行方法传递参数.
第二种是scrapy.Request的方法,利用这个方法本身自带的meta变量进行传参
第一种方法代码如下:
def parse(self, response):
# 确定章节在文章中的位
for i in response.xpath('//*[@id="list"]//dd/a/@href').extract()[13:]:
item = TianfushuItem()
# 取章节网页.html前的四位数字做章节标识名,作为今后排序的依据.
item['name'] = int(i[-9:-5])
# 直接把item作为参数传递给下一个解析器
yield scrapy.Request(self.url + i, callback=lambda rsp, it=item: self.parse_item(response=rsp, item=it))
def parse_item(self, response, item):
item['content'] = '\t\t\t\t\t'*2 + response.xpath('//div[@class="bookname"]/h1/text()').extract()[0] + '\n\n\n'+ '\n\n\n'.join([' ' + i.strip() for i in response.xpath('//div[@id="content"]/text()').extract()
if i.strip()]) + '\n\n'
yield item
这种方法,把本来的回调函数用lambda函数装起来, lambda函数接收2个值, 其中一个默认为item(必须在建立lambda函数的时候就把值传给它,不然今后的值会变,for循环后的item已经不是当前的item了,实测),由于有了默认值,Request的返回的response对象会自动去填充lambda函数的另一个参数rsp.这样, 被装在里边的函数就得到response对象和item.
第二种方法代码示例如下:
def parse(self, response):
# 确定章节在文章中的位置,并写入item
for i in response.xpath('//*[@id="list"]//dd/a/@href').extract()[13:]:
item = TianfushuItem()
# 取章节网页.html前的四位数字做章节标识名,作为今后排序的依据.
item['name'] = int(i[-9:-5])
yield scrapy.Request(self.url + i, callback=self.parse_item, meta=({'item': item}))
def parse_item(self, response):
item = response.meta['item']
item['content'] = '\t\t\t\t\t'*2 + response.xpath('//div[@class="bookname"]/h1/text()').extract()[0] + '\n\n\n'+ '\n\n\n'.join([' ' + i.strip() for i in response.xpath('//div[@id="content"]/text()').extract()
if i.strip()]) + '\n\n'
yield item
通过meta参数做为桥梁.就把第一个parser实例化并作出部分填充的的item做为实参传递给了第二个parser