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

猜你喜欢

转载自www.cnblogs.com/sgsg/p/10857695.html
今日推荐