文章目录
1. 前言
Scrapy
并不是直接填充items,而是有自己的机制。
items
为爬取的数据提供容器,Item Loader
为该容器提供了填充机制。
2. 使用Item Loader
from scrapy.loader import ItemLoader
from myproject.items import Product
def parse(self, response):
l = ItemLoader(item=Product(), response=response)
l.add_xpath('name', '//div[@class="product_name"]')
l.add_xpath('name', '//div[@class="product_title"]')
l.add_xpath('price', '//p[@id="price"]')
l.add_css('stock', 'p#stock]')
l.add_value('last_updated', 'today') # you can also use literal values
return l.load_item()
3. 输入和输出处理器
一个Item Loader
为每一个 item的字段都包含了一个输入处理器和输出处理器。
- 当提取的数据被
Item Loader
接收(如:add_xpath()
,add_css()
,add_value()
方法)时会使用输入处理器处理它们,并保存在ItemLoader
中。 - 然后调用
ItemLoader.load_item()
方法获得Item对象并在输出处理器处理这写数据之后进行填充到item中。
举个例子,
l = ItemLoader(Product(), some_selector)
l.add_xpath('name', xpath1) # (1)
l.add_xpath('name', xpath2) # (2)
l.add_css('name', css) # (3)
l.add_value('name', 'test') # (4)
return l.load_item() # (5)
- 数据从
xpath1
抽取出来,传递给name
字段的输入处理器。输入处理器的结果存在ItemLoader
中。 - 与第一步类似。输入处理器的结果
append
到第一步的结果中。 - 与第二步类似。只不过是从
CSS 选择器
中提取数据。将结果append
到之前的结果中。 - 与第三步类似。只不过此次不需要从选择器中提取数据(数据直接给了)。结果
append
到之前的结果中。 - 将1, 2,3, 4步中收集的数据传递给对应字段的输出处理器。将输出处理器的结果分配给item中的对应字段。
值得注意的是,处理器只是可调用对象,用要解析的数据调用,并返回一个已解析的值。所以您可以使用任何函数作为输入或输出处理器。唯一的要求是他们必须接受一个(并且只有一个)为可迭代对象的位置参数。
输入和输出处理器都必须接收一个可迭代对象作为它们的第一个参数。这些函数的输出可以是任何东西。输入处理器的结果将附加到包含收集值(针对该字段)的内部列表(在加载程序中)。输出处理器的结果是最终分配给该项的值。
您需要记住的另一件事是,输入处理器返回的值在内部收集(在列表中),然后传递给输出处理器来填充字段。
4. 声明Item Loader
通过定义一个类来声明。
from scrapy.loader import ItemLoader
from scrapy.loader.processors import TakeFirst, MapCompose, Join
class ProductLoader(ItemLoader):
default_output_processor = TakeFirst()
name_in = MapCompose(unicode.title) # name字段的输入处理器
name_out = Join() # name字段的输出处理器
price_in = MapCompose(unicode.strip)
# ...
5. 声明 输入/输出处理器
输入/输出处理器可以在Item Loader
定义中声明。还可以在Item Field
元素内指明输入/输出处理器。
import scrapy
from scrapy.loader.processors import Join, MapCompose, TakeFirst
from w3lib.html import remove_tags
def filter_price(value):
if value.isdigit():
return value
class Product(scrapy.Item):
name = scrapy.Field(
input_processor=MapCompose(remove_tags),
output_processor=Join(),
)
price = scrapy.Field(
input_processor=MapCompose(remove_tags, filter_price),
output_processor=TakeFirst(),
)
输入和输出处理器的优先顺序如下:
Item Loader
字段特定属性:field_in
和field_out
(最优先)- 字段元数据 (
input_processor
和output_processor
关键字参数) Item Loader
默认值:ItemLoader.default_input_processor()
和ItemLoader.default_output_processor()
(最低优先级)
6. Item Loder 上下文
Item Loder
上下文是任意键/值
的字典,在项加载器中的所有输入和输出处理器之间共享。 可以在声明,实例化或使用Item Loader
时传递。它们用于修改输入/输出处理器的行为
。
如果你想根据Item Loader
上下文的中的内容修改输入/输出处理器的行为。就用它呗。
7. 嵌套Loader
从文档的子部分分析相关值时,创建嵌套加载器可能很有用。假设您正在从一个页面的页脚提取细节。