声明项目加载器
from scrapy.loader import ItemLoader
from scrapy.loader.processors import TakeFirst, MapCompose, Join
class DemoLoader(ItemLoader):
default_output_processor = TakeFirst()
title_in = MapCompose(unicode.title)
title_out = Join()
size_in = MapCompose(unicode.strip)
# you can continue scraping here
在上面的代码可以看到,输入处理器使用 _id 作为后缀以及输出处理器声明使用_out 作为后缀声明。ItemLoader.default_input_processor 和 ItemLoader.default_output_processor 属性用于声明默认输入/输出处理器。
使用项目加载器来填充项目
-
可以使用选择器来收集值到项目加载器。
-
可以在同一项目字段中添加更多的值,项目加载器将使用相应的处理程序来添加这些值。
from scrapy.loader import ItemLoader
from demoproject.items import Demo
def parse(self, response):
l = ItemLoader(item = Product(), response = response)
l.add_xpath("title", "//div[@class='product_title']")
l.add_xpath("title", "//div[@class='product_name']")
l.add_xpath("desc", "//div[@class='desc']")
l.add_css("size", "div#size]")
l.add_value("last_updated", "yesterday")
return l.load_item()
1. //div[@class="product_title"] 2. //div[@class="product_name"]
此后,类似请求用于内容描述(desc)字段。size数据使用 add_css()方法提取和last_updated 使用add_value()方法使用值“yesterday”来填充。
输入和输出处理器
-
当提取数据时,输入处理器处理结果,交将结果存储在数据加载器。
-
接下来,收集数据后,调用 ItemLoader.load_item() 方法来获得 Item 对象。
-
最后,指定输出处理器到该项目的结果。
l = ItemLoader(Product(), some_selector)
l.add_xpath("title", xpath1) # [1]
l.add_xpath("title", xpath2) # [2]
l.add_css("title", css) # [3]
l.add_value("title", "demo") # [4]
return l.load_item() # [5]
-
第1行: 标题(title)的数据是从xpath1提取并通过输入处理器,其结果被收集并存储在 ItemLoader 中。
-
第2行: 同样地,标题(title)从xpath2提取并通过相同的输入处理器,其结果收集的数据加到[1]中。
-
第3行: 标题(title)被从css选择萃取和通过相同的输入处理器传递并将收集的数据结果加到[1]及[2]。
-
第4行: 接着,将“demo”值分配并传递到输入处理器。
-
第5行: 最后,数据是从所有字段内部收集并传递给输出处理器,最终值将分配给项目。
声明输入和输出处理器
输入和输出的处理器在项目加载器(ItemLoader )定义声明。除此之外,它们还可以在项目字段的元数据指定。
例如:
import scrapy
from scrapy.loader.processors import Join, MapCompose, TakeFirst
from w3lib.htmll import remove_tags
def filter_size(value):
if value.isdigit():
return value
class Item(scrapy.Item):
name = scrapy.Field(
input_processor = MapCompose(remove_tags),
output_processor = Join(),
)
size = scrapy.Field(
input_processor = MapCompose(remove_tags, filter_price),
output_processor = TakeFirst(),
)
>>> from scrapy.loader import ItemLoader
>>> il = ItemLoader(item=Product())
>>> il.add_value('title', [u'Hello', u'<strong>world</strong>'])
>>> il.add_value('size', [u'<span>100 kg</span>'])
>>> il.load_item()
{'title': u'Hello world', 'size': u'100 kg'}
项目加载器上下文
def parse_length(text, loader_context):
unit = loader_context.get('unit', 'cm')
# You can write parsing code of length here
return parsed_length
通过接收loader_context参数,它告诉项目加载器可以收到项目加载器上下文。有几种方法可以改变项目加载器上下文的值:
-
修改当前的活动项目加载器上下文:
loader = ItemLoader (product) loader.context ["unit"] = "mm"
-
在项目加载器实例中修改:
loader = ItemLoader(product, unit="mm")
-
在加载器项目声明与项目加载器上下文实例输入/输出处理器中修改:
class ProductLoader(ItemLoader): length_out = MapCompose(parse_length, unit="mm")
ItemLoader对象
class scrapy.loader.ItemLoader([item, selector, response, ]**kwargs)
| S.N. | 参数 & 描述 |
|---|---|
| 1 |
item 它是通过 calling add_xpath(), add_css() 或 add_value()的填充项 |
| 2 |
selector
它用来从网站提取数据
|
| 3 |
response
它是用 default_selector_class 来构造选择器
|
| S.N. | 方法 & 描述 | 示例 |
|---|---|---|
| 1 |
get_value(value, *processors, **kwargs)
由一个给定的处理器和关键字参数,该值在getValue()方法处理
|
>>> from scrapy.loader.processors import TakeFirst
>>> loader.get_value(u'title: demoweb', TakeFirst(), unicode.upper, re='title: (.+)')
'DEMOWEB`
|
| 2 |
add_value(field_name, value, *processors, **kwargs) 它首先通过get_value传递处理值,并增加到字段中 |
loader.add_value('title', u'DVD')
loader.add_value('colors', [u'black', u'white'])
loader.add_value('length', u'80')
loader.add_value('price', u'2500')
|
| 3 |
replace_value(field_name, value, *processors, **kwargs)
它用一个新值替换所收集的数据
|
loader.replace_value('title', u'DVD')
loader.replace_value('colors', [u'black', u'white'])
loader.replace_value('length', u'80')
loader.replace_value('price', u'2500')
|
| 4 |
get_xpath(xpath, *processors, **kwargs)
它用于由接到的XPath给处理器和关键字参数提取unicode字符串
|
# HTML code: <div class="item-name">DVD</div>
loader.get_xpath("//div[@class='item-name']")
# HTML code: <div id="length">the length is 45cm</div>
loader.get_xpath("//div[@id='length']", TakeFirst(), re="the length is (.*)")
|
| 5 |
add_xpath(field_name, xpath, *processors, **kwargs)
它接收XPath提取unicode字符串到字段中
|
# HTML code: <div class="item-name">DVD</div>
loader.add_xpath('name', '//div[@class="item-name"]')
# HTML code: <div id="length">the length is 45cm</div>
loader.add_xpath('length', '//div[@id="length"]', re='the length is (.*)')
|
| 6 |
replace_xpath(field_name, xpath, *processors, **kwargs)
它使用XPath取换了从网站收集的数据
|
# HTML code: <div class="item-name">DVD</div>
loader.replace_xpath('name', '//div[@class="item-name"]')
# HTML code: <div id="length">the length is 45cm</div>
loader.replace_xpath('length', '//div[@id="length"]', re='the length is (.*)')
|
| 7 |
get_css(css, *processors, **kwargs)
它接收用于提取unicode字符串的CSS选择器
|
loader.get_css("div.item-name")
loader.get_css("div#length", TakeFirst(), re="the length is (.*)")
|
| 8 |
add_css(field_name, css, *processors, **kwargs)
它类似于add_value()方法,它增加CSS选择器到字段中
|
loader.add_css('name', 'div.item-name')
loader.add_css('length', 'div#length', re='the length is (.*)')
|
| 9 |
replace_css(field_name, css, *processors, **kwargs)
它使用CSS选择器取代了提取的数据
|
loader.replace_css('name', 'div.item-name')
loader.replace_css('length', 'div#length', re='the length is (.*)')
|
| 10 |
load_item()
当收集数据后,这个方法填充收集到数据的项目并返回
|
def parse(self, response):
l = ItemLoader(item=Product(), response=response)
l.add_xpath('title', '//div[@class="product_title"]')
loader.load_item()
|
| 11 |
nested_xpath(xpath)
它是通过XPath选择器来创建嵌套加载器
|
loader = ItemLoader(item=Item())
loader.add_xpath('social', 'a[@class = "social"]/@href')
loader.add_xpath('email', 'a[@class = "email"]/@href')
|
| 12 |
nested_css(css)
它被用来创建一个CSS选择器嵌套加载器
|
loader = ItemLoader(item=Item())
loader.add_css('social', 'a[@class = "social"]/@href')
loader.add_css('email', 'a[@class = "email"]/@href')
|
| S.N. | 属性 & 描述 |
|---|---|
| 1 |
item
它是项目加载器进行解析的对象
|
| 2 |
context
这是项目加载器是活跃的当前上下文
|
| 3 |
default_item_class
如果在构造没有给出,它用来表示项
|
| 4 |
default_input_processor
不指定输入处理器中的字段,只有一个用于其默认输入处理器
|
| 5 |
default_output_processor
不指定输出处理器中的字段,只有一个用于其默认的输出处理器
|
| 6 |
default_selector_class
如果它没有在构造给定,它是使用来构造选择器的一个类
|
| 7 |
selector
它是一个用来从站点提取数据的对象
|
嵌套加载器
这是使用从文档解析分段的值来创建嵌套加载器。如果不创建嵌套装载器,需要为您想提取的每个值指定完整的XPath或CSS。
<header> <a class="social" href="http://facebook.com/whatever">facebook</a> <a class="social" href="http://twitter.com/whatever">twitter</a> <a class="email" href="mailto:someone@example.com">send mail</a> </header>
loader = ItemLoader(item=Item())
header_loader = loader.nested_xpath('//header')
header_loader.add_xpath('social', 'a[@class = "social"]/@href')
header_loader.add_xpath('email', 'a[@class = "email"]/@href')
loader.load_item()
重用和扩展项目加载器
举例来说,假设一个网站自己的产品名称是由三条短线封闭的(例如: ---DVD---)。 您可以通过重复使用默认产品项目加载器,如果你不希望它在最终产品名称所示,下面的代码删除这些破折号:
from scrapy.loader.processors import MapCompose
from demoproject.ItemLoaders import DemoLoader
def strip_dashes(x):
return x.strip('-')
class SiteSpecificLoader(DemoLoader):
title_in = MapCompose(strip_dashes, DemoLoader.title_in)
可用内置处理器
-
class scrapy.loader.processors.Identity
它返回原始的值而并不修改它。 例如:>>> from scrapy.loader.processors import Identity >>> proc = Identity() >>> proc(['a', 'b', 'c']) ['a', 'b', 'c']
-
class scrapy.loader.processors.TakeFirst
它返回一个值来自收到列表的值即非空/非null值。 例如:>>> from scrapy.loader.processors import TakeFirst >>> proc = TakeFirst() >>> proc(['', 'a', 'b', 'c']) 'a'
-
class scrapy.loader.processors.Join(separator = u' ')
它返回附连到分隔符的值。默认的分隔符是 u'',这相当于于 u' '.join 的功能。例如:>>> from scrapy.loader.processors import Join >>> proc = Join() >>> proc(['a', 'b', 'c']) u'a b c' >>> proc = Join('<br>') >>> proc(['a', 'b', 'c']) u'a<br>b<br>c' -
class scrapy.loader.processors.SelectJmes(json_path)
此类查询使用提供JSON路径值,并返回输出。例如:>>> from scrapy.loader.processors import SelectJmes, Compose, MapCompose >>> proc = SelectJmes("hello") >>> proc({'hello': 'scrapy'}) 'scrapy' >>> proc({'hello': {'scrapy': 'world'}}) {'scrapy': 'world'}下面是一个查询通过导入JSON值的代码:>>> import json >>> proc_single_json_str = Compose(json.loads, SelectJmes("hello")) >>> proc_single_json_str('{"hello": "scrapy"}') u'scrapy' >>> proc_json_list = Compose(json.loads, MapCompose(SelectJmes('hello'))) >>> proc_json_list('[{"hello":"scrapy"}, {"world":"env"}]') [u'scrapy']