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 屬性用于聲明默認(rèn)輸入/輸出處理器。
from scrapy.loader import ItemLoader from demoproject.items import Demo def parse(self, response): l = ItemLoader(item = Product(), response = response) l.add_xpath("title", "http://div[@class='product_title']") l.add_xpath("title", "http://div[@class='product_name']") l.add_xpath("desc", "http://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"]
此后,類似請求用于內(nèi)容描述(desc)字段。size數(shù)據(jù)使用 add_css()方法提取和last_updated 使用add_value()方法使用值“yesterday”來填充。
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行: 標(biāo)題(title)的數(shù)據(jù)是從xpath1提取并通過輸入處理器,其結(jié)果被收集并存儲在 ItemLoader 中。
第2行: 同樣地,標(biāo)題(title)從xpath2提取并通過相同的輸入處理器,其結(jié)果收集的數(shù)據(jù)加到[1]中。
第3行: 標(biāo)題(title)被從css選擇萃取和通過相同的輸入處理器傳遞并將收集的數(shù)據(jù)結(jié)果加到[1]及[2]。
第4行: 接著,將“demo”值分配并傳遞到輸入處理器。
第5行: 最后,數(shù)據(jù)是從所有字段內(nèi)部收集并傳遞給輸出處理器,最終值將分配給項(xiàng)目。
輸入和輸出的處理器在項(xiàng)目加載器(ItemLoader )定義聲明。除此之外,它們還可以在項(xiàng)目字段的元數(shù)據(jù)指定。
例如:
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參數(shù),它告訴項(xiàng)目加載器可以收到項(xiàng)目加載器上下文。有幾種方法可以改變項(xiàng)目加載器上下文的值:
loader = ItemLoader (product) loader.context ["unit"] = "mm"
loader = ItemLoader(product, unit="mm")
class ProductLoader(ItemLoader): length_out = MapCompose(parse_length, unit="mm")
class scrapy.loader.ItemLoader([item, selector, response, ]**kwargs)
S.N. | 參數(shù) & 描述 |
---|---|
1 |
item 它是通過 calling add_xpath(), add_css() 或 add_value()的填充項(xiàng) |
2 |
selector
它用來從網(wǎng)站提取數(shù)據(jù)
|
3 |
response
它是用 default_selector_class 來構(gòu)造選擇器
|
S.N. | 方法 & 描述 | 示例 |
---|---|---|
1 |
get_value(value, *processors, **kwargs)
由一個(gè)給定的處理器和關(guān)鍵字參數(shù),該值在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)
它用一個(gè)新值替換所收集的數(shù)據(jù)
|
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給處理器和關(guān)鍵字參數(shù)提取unicode字符串
|
# HTML code: <div class="item-name">DVD</div> loader.get_xpath("http://div[@class='item-name']") # HTML code: <div id="length">the length is 45cm</div> loader.get_xpath("http://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取換了從網(wǎng)站收集的數(shù)據(jù)
|
# 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選擇器取代了提取的數(shù)據(jù)
|
loader.replace_css('name', 'div.item-name') loader.replace_css('length', 'div#length', re='the length is (.*)') |
10 |
load_item()
當(dāng)收集數(shù)據(jù)后,這個(gè)方法填充收集到數(shù)據(jù)的項(xiàng)目并返回
|
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選擇器來創(chuàng)建嵌套加載器
|
loader = ItemLoader(item=Item()) loader.add_xpath('social', 'a[@class = "social"]/@href') loader.add_xpath('email', 'a[@class = "email"]/@href') |
12 |
nested_css(css)
它被用來創(chuàng)建一個(gè)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
它是項(xiàng)目加載器進(jìn)行解析的對象
|
2 |
context
這是項(xiàng)目加載器是活躍的當(dāng)前上下文
|
3 |
default_item_class
如果在構(gòu)造沒有給出,它用來表示項(xiàng)
|
4 |
default_input_processor
不指定輸入處理器中的字段,只有一個(gè)用于其默認(rèn)輸入處理器
|
5 |
default_output_processor
不指定輸出處理器中的字段,只有一個(gè)用于其默認(rèn)的輸出處理器
|
6 |
default_selector_class
如果它沒有在構(gòu)造給定,它是使用來構(gòu)造選擇器的一個(gè)類
|
7 |
selector
它是一個(gè)用來從站點(diǎn)提取數(shù)據(jù)的對象
|
這是使用從文檔解析分段的值來創(chuàng)建嵌套加載器。如果不創(chuàng)建嵌套裝載器,需要為您想提取的每個(gè)值指定完整的XPath或CSS。
<header> <a class="social" >facebook</a> <a class="social" >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()
舉例來說,假設(shè)一個(gè)網(wǎng)站自己的產(chǎn)品名稱是由三條短線封閉的(例如: ---DVD---)。 您可以通過重復(fù)使用默認(rèn)產(chǎn)品項(xiàng)目加載器,如果你不希望它在最終產(chǎn)品名稱所示,下面的代碼刪除這些破折號:
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
>>> from scrapy.loader.processors import TakeFirst >>> proc = TakeFirst() >>> proc(['', 'a', 'b', 'c']) 'a'
class scrapy.loader.processors.Join(separator = u' ')
>>> 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)
>>> from scrapy.loader.processors import SelectJmes, Compose, MapCompose >>> proc = SelectJmes("hello") >>> proc({'hello': 'scrapy'}) 'scrapy' >>> proc({'hello': {'scrapy': 'world'}}) {'scrapy': 'world'}
>>> 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']