为什么在 Scrapy 中抓取的文本在蜘蛛中是字符串,而在管道中是列表?

Why in Scrapy scraped text is as string in spider, but as list in pipeline?

有人可以给我解释一下吗?
在我的蜘蛛中,我有使用 XPath 提取数据的代码。

price_euro = add.xpath('.//strong[@class="price price--eur"]/text()').extract_first()
print 'price_euro', price_euro, type(price_euro)

我得到的是:

price_euro 25.500  <type 'unicode'>

我明白这一点,我把它作为一个字符串(Unicode),因为我使用了 .extract_first() ,这就是我想要的。

但在我的管道中,

print "item['price_euro']", item['price_euro'], type(item['price_euro'])

我有一个列表

item['price_euro'] [u'25.500 '] <type 'list'>

这对我来说不是什么大问题,但很烦人,因为每次我想访问它时都需要在它的末尾添加 [0]。例如。项目['price_euro'][0]

我可以禁用它吗?
这背后的逻辑是什么?

谢谢

我如何添加price_euro

l = ItemLoader(item=MyItem(), response=response)
l.add_value('price_euro', price_euro)      
yield l.load_item()   

ItemLoader 允许调用 add_value()(以及 add_css()add_xpath()同一字段多次 .当您要查找的信息可以在 HTML 源的多个位置找到时,或者当 HTML 布局因请求而异时,这将很有帮助。为了适应这一点,项目加载器将所有字段值存储在列表中。

当您期望该字段只有一个值时(对于您的价格信息),您可以通过指定 output processor 告诉项目加载器如何在调用 load_item() 时转换列表。做到这一点的规范方法是通过 subclassing ItemLoader class:

from scrapy.loader import ItemLoader
from scrapy.loader.processors import TakeFirst

class MyItemLoader(ItemLoader):
    default_item_class = MyItem
    price_euro_out = TakeFirst()

然后您可以像以前一样填充此项目加载器,还有一个好处是您不再需要告诉项目加载器要使用哪种项目类型:

l = MyItemLoader(response=response)
l.add_value('price_euro', price_euro)      
yield l.load_item()  

对于您发布的示例代码,您甚至可以避免通过 add_xpath() 方法手动提取并将 add 作为 selector 关键字参数传递给项目加载器:

l = MyItemLoader(selector=add)
l.add_xpath('price_euro', './/strong[@class="price price--eur"]/text()')      
yield l.load_item()  

如果您想为项目的 所有 字段启用此 "take the first list element" 行为,您还可以为项目加载器声明默认输出处理器:

class MyItemLoader(ItemLoader):
    default_item_class = MyItem
    default_output_processor = TakeFirst()

Scrapy 文档有 list of built-in processors.