我正在尝试使用scrapy itemloader,我以前只是项目,我希望我的代码更少 例如: 如果我想从页面解析汽车信息列表,我需要car_name,car_color ...但对于某些汽车,颜色为None, 我以前这样写:
cars = response.xpath(carsxpath)
for car in cars:
car_name = car.xpath(car_name_xpath)
car_color = car.xpath(car_color_xpath)
item = CarItem()
item['car_name'] = car_name
item['car_color'] = car_color
yield item
但是最近,我找到了Itemloader,它可以简化代码,从文档中,我发现它的工作原理如下:
loader = ItemLoader(item={}, response=response)
carloader = loader.nested_xpath('car_xpath')
carloader.add('car_name', car_name_xpath)
carloader.add('car_color', car_color_xpath)
cars = loader.load_item()
因为我发现它之前不需要像car_name,car_color这样的tmp var,但是使用这个问题,汽车就是列表的字典,比如
cars = {'car_name':[car_names],'car_color':[car_colors]}
但这对于产生项目是不方便的,我想获得像
这样的输出cars = [{'carname':carname1,'carclor':carcolor1'}, {'carname':carname2,'carclor':carcolor2'}...]
所以我的问题是'有没有办法在scrapy本身处理这个?',如果我需要处理更多,我宁愿使用我以前的方式,而不是Itemloader
答案 0 :(得分:0)
您可以为ItemLoader指定一些处理器,这些处理器会在将值添加到项目加载器后对该值执行某些操作。例如,添加项目时只需要第一个元素:
from scrapy.loader.processors import TakeFirst()
loader = ItemLoader(item={}, response=response)
carloader = loader.nested_xpath('car_xpath')
carloader.car_name_out = TakeFirst()
carloader.add('car_name', car_name_xpath)
carloader.car_color_out = TakeFirst()
carloader.add('car_color', car_color_xpath)
cars = loader.load_item()
更优雅地看起来像:
class MyLoader(ItemLoader):
default_item_class = dict
car_name_out = TakeFirst()
car_color_out = TakeFirst()
class MySpider(scrapy.Spider):
loader = MyLoader(item={}, response=response)
carloader = loader.nested_xpath('car_xpath')
carloader.add('car_name', car_name_xpath)
carloader.add('car_color', car_color_xpath)
cars = loader.load_item()
答案 1 :(得分:0)
ItemLoader
旨在填充单个项目,而不是其中的列表,因此最好使用以下内容:
for sel in response.xpath('car_xpath'):
l = ItemLoader(selector=sel)
l.add_xpath('car_name', car_name_xpath)
l.add_xpath('car_color', car_color_xpath)
yield l.load_item()
这完全合并了你以前的方法和ItemLoader的用法。