Scrapy的Item Loaders
Item
提供抓取数据的容器,而Item Loader
提供了填充该容器的机制。
Item Loader用法
from scrapy.loader import ItemLoader
from test.items import DemoItem
def parse(self, response):
loader = ItemLoader(item=DemoItem(), response=response)
loader.add_xpath('name', '//div[@class="name"]')
loader.add_xpath('name', '//div[@class="title"]')
loader.add_css('value', 'p#value')
loader.add_value('key', 'key1')
yield loader.load_item()
- 填充值的方法有三种。
- 同一个值
name
可以多次填充内容。 loader.load_item()
返回填充先前提取并收集到的数据。
输入和输出处理器
- 项目加载器对于每个字段包含一个 输入处理器 和 输出处理器 。
- 输入处理器 接受处理所提取的数据(add_xpath、add_css、add_value) 和输入处理器的结果被收集并保持
ItemLoader
内部。 - 收集数据后,调用
load_item()
方法来填充Item
对象。 - 输出处理器 分配给各项目最终值。
1) loader.add_xpath('name', 'xpath1')
2) loader.add_xpath('name', 'xpath2')
3) loader.add_css('value', 'css')
4) loader.add_value('key', 'value')
5) yield loader.load_item()
- 经过
xpath1
提取数据,通过输入处理器的name
字段, 输入处理器的结果 被收集并保存在项目加载器中(暂时未分配给项目)。 - 经过
xpath2
提取数据,使用和xpath1
同一个输入处理器, 输入处理器的结果 加到(1)
中收集的数据。 - 经过
CSS
选择器提取,通过输入处理器的value
字段,收集保存在项目加载器中。 - 通过
add_value()
添加的值 不能迭代 ,因此在传递给 输入处理器之前 ,会被转化为单个元素可迭代,因为 输入处理器只接受迭代 。 - 以上收集的数据通过对应的字段 输出处理器 。输出处理器的结果是 分配对应字段的值 。
注意
输入和输出处理器都必须接收一个迭代器作为它们的第一个参数。
输入处理器的结果将附加到包含收集的值(对于该字段)的 内部列表 (在加载程序中)。
输出处理器的结果是最终分配给项目的值。
项目加载器
项目加载器通过使用类定义语法声明为Items
from scrapy.loader import ItemLoader
from scrapy.loader.processors import TakeFirst, Join, Compose, Identity, MapCompose
class NewsLoader(ItemLoader):
default_input_processor = TakeFirst()
default_output_processor = Compose(Join(), lambda x: x.strip())
name_in = MapCompose(lambda x: x.strip())
name_out = Compose(Join())
- 默认输入/输出处理器
default_input_processor
default_output_processor
- 输入处理器在字段后+
_in
后缀来声明,输出处理器在字段后+_out
后缀声明。
输入和输出处理器
- 输入和输出处理器可以在
Item Loader
定义中声明,这种方式声明输入处理器是很常见的。 - 在项目字段元数据中可以指定要使用的输入和输出处理器。
import scrapy
from scrapy.loader.processors import Join, MapCompose, TakeFirst
class DemoItem(scrapy.Item):
name = scrapy.Field(
input_processor=MapCompose(lambda x:x.strip()),
output_processor=Join('、'),
)
value = scrapy.Field(
input_processor=Compose(Join())
output_processor=TakeFirst(),
)
优先级顺序
- 项目加载器字段属性:
name_in
和name_out
(最高级) - 字段元数据:
input_processor
和output_processor
- 项目加载器默认值:
ItemLoader.default_input_processor
和ItemLoader.default_output_processor
(最低优先级)
项目加载器上下文
项目加载器上下文是在项目加载器中的 所有输入和输出处理器之间共享 的任意键/值的
dict
。
ItemLoader对象
源码实现
class ItemLoader(object):
default_item_class = Item
default_input_processor = Identity()
default_output_processor = Identity()
default_selector_class = Selector
def __init__(self, item=None, selector=None, response=None, parent=None, **context):
if selector is None and response is not None:
selector = self.default_selector_class(response)
self.selector = selector
context.update(selector=selector, response=response)
if item is None:
item = self.default_item_class()
self.context = context
self.parent = parent
self._local_item = context['item'] = item
self._local_values = defaultdict(list)
- 当
item=None
将使用类中已经实例化的default_item_class
。 - 使用选择器或响应参数实例化时,
ItemLoader
类提供了使用选择器从网页提取数据的方便的机制。
item
:项目实例来填充以后调用add_xpath()
selector
:使用add_xpath()
方法时,从中提取数据的选择器。response
:它是用default_selector_class
来构造选择器- 项目,选择器,响应和剩余的关键字参数被分配给Loader上下文(可通过context属性访问)。
ItemLoader对象
-
get_value(self, value, *processors, **kw):
- 通过给定的
processors
和关键字参数处理给定的value
- 可用关键字参数:
re
- 通过给定的
-
add_value(self, field_name, value, *processors, **kw):
- 首先通过
get_value
为该字段收集数据。
- 首先通过
-
replace_value(self, field_name, value, *processors, **kw):
- 与
add_value
类似,但是这里时替换数据。
- 与
-
load_item()
使用目前收集的数据填充项目,并返回。收集的数据首先通过 输出处理器,以获得要分配给每个项目字段的最终值。 -
nested_xpath(xpath)
使用xpath选择器创建嵌套加载器。所提供的选择器应用于与此 ItemLoader 关联的选择器。 -
nested_css(css)
功能类似 -
get_collected_values(field_name)
返回给定字段的收集值。 -
get_output_value(field_name)
返回给定字段使用输出处理器解析的收集值。此方法根本不填充或修改项目。 -
get_input_processor(field_name)
返回给定字段的输入处理器。 -
get_output_processor(field_name)
返回给定字段的输出处理器。
ItemLoader实例方法
item
:该项装载器将解析 Item 对象。context
:此项目加载程序的当前活动 上下文。default_item_class
:Item
类(或工厂),用于在构造函数中未给出时实例化项。default_input_processor
:用于不指定一个字段的字段的默认输入处理器。default_output_processor
:用于不指定一个字段的字段的默认输出处理器。default_selector_class
:用于构造此ItemLoader
的selector
的类,如果在构造函数中仅给出响应。如果在构造函数中给出了选择器,则忽略此属性。此属性有时在子类中被覆盖。selector
:从中提取数据的Selector
对象。它是在构造函数中给出的选择器,或者是从使用default_selector_class
的构造函数中给出的响应中创建的。此属性意味着是只读的。
内置处理器
- Identity:返回原始值而不修改
- TakeFirst:返回一个收到列表的值非空值(第一个为空,往后递归)
- Join:链接的分割值,默认为空。和’’.join()用法类似
- SelectJmes:查询JSON路径
- Compose:由给定函数的组合构成的处理器。这意味着该处理器的每个输入值都被传递给第一个函数,并且该函数的结果被传递给第二个函数,依此类推,直到最后一个函数返回该处理器的输出值。
- 默认情况下,停止进程None值。可以通过传递关键字参数来更改此行为stop_on_none=False。
- 每个功能可以可选地接收loader_context参数。对于那些处理器,这个处理器将通过该参数传递当前活动的Loader上下文。
- MapCompose:与处理器类似,由给定功能的组成构成的Compose处理器。与此处理器的区别在于内部结果在函数之间传递的方式。
- 每个特定函数可以返回值或值列表,这些值通过应用于其他输入值的相同函数返回的值列表展平。函数也可以返回None,在这种情况下,该函数的输出将被忽略,以便在链上进行进一步处理。
- 此处理器提供了一种方便的方法来组合只使用单个值(而不是iterables)的函数。由于这个原因, MapCompose处理器通常用作输入处理器,因为数据通常使用选择器的 extract()方法提取。