Scrapy-Item Loaders(项目加载器)
?
Item Loaders:http://doc.scrapy.org/en/latest/topics/loaders.html
Item Loaders(中文版):https://scrapy-chs.readthedocs.io/zh_CN/latest/topics/loaders.html
?
?
?
項(xiàng)目加載器
?
Item Loaders(項(xiàng)目加載器) 提供了一種方便的機(jī)制來(lái)填充抓取的項(xiàng)目。即使 可以使用自己的類(lèi)似字典的API填充項(xiàng)目,Item Loaders(項(xiàng)目加載器)提供了一個(gè)更方便的API,通過(guò)自動(dòng)化一些常見(jiàn)的任務(wù),如解析原始提取的數(shù)據(jù),然后分配它從剪貼過(guò)程中填充他們。
換句話(huà)說(shuō),items 提供了抓取數(shù)據(jù)的容器,而 Item Loader 提供了填充該容器的機(jī)制。
Item Loaders(項(xiàng)目加載器)旨在提供一種靈活,高效和容易的機(jī)制,通過(guò)爬蟲(chóng)或源格式(HTML,XML等)擴(kuò)展和覆蓋不同的字段解析規(guī)則,而不會(huì)成為維護(hù)的噩夢(mèng)。
?
?
使用裝載機(jī)項(xiàng)目來(lái)填充的項(xiàng)目
?
要使用項(xiàng)目加載器,您必須首先實(shí)例化它。您可以使用類(lèi)似dict的對(duì)象(例如Item或dict)實(shí)例化它,也可以不使用它,在這種情況下,項(xiàng)目將在Item Loader構(gòu)造函數(shù)中使用屬性中指定的Item類(lèi)自動(dòng)ItemLoader.default_item_class?實(shí)例化。
然后,您開(kāi)始收集值到項(xiàng)裝載程序,通常使用選擇器。您可以向同一項(xiàng)目字段添加多個(gè)值; 項(xiàng)目加載器將知道如何使用適當(dāng)?shù)奶幚砗瘮?shù)“加入”這些值。
這里是?Spider?中典型的 Item Loader 用法,使用?Items部分?中聲明的?Product?項(xiàng):
from scrapy.loader import ItemLoader from myproject.items import Productdef 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 valuesreturn l.load_item()通過(guò)快速查看該代碼,我們可以看到該?name字段正從頁(yè)面中兩個(gè)不同的XPath位置提取:
換句話(huà)說(shuō),通過(guò)使用?add_xpath()方法從兩個(gè)XPath位置提取數(shù)據(jù)來(lái)收集數(shù)據(jù)。這是稍后將分配給name字段的數(shù)據(jù)。
之后,類(lèi)似的調(diào)用用于?price?和?stock?字段(后者使用帶有add_css()方法的CSS選擇器),最后使用不同的方法last_update直接使用文字值(today)填充字段add_value()。
最后,收集的所有數(shù)據(jù)時(shí),該?ItemLoader.load_item()方法被稱(chēng)為實(shí)際上返回填充先前提取并與收集到的數(shù)據(jù)的項(xiàng)目add_xpath(),?add_css()和add_value()調(diào)用。
?
?
輸入和輸出處理器
?
項(xiàng)目加載器對(duì)于每個(gè)(項(xiàng)目)字段包含一個(gè)輸入處理器和一個(gè)輸出處理器。輸入處理器只要它的接收處理所提取的數(shù)據(jù)(通過(guò)add_xpath(),add_css()或 add_value()方法)和輸入處理器的結(jié)果被收集并保持ItemLoader內(nèi)部。收集所有數(shù)據(jù)后,ItemLoader.load_item()調(diào)用該 方法來(lái)填充和獲取填充 Item對(duì)象。這是當(dāng)輸出處理器使用先前收集的數(shù)據(jù)(并使用輸入處理器處理)調(diào)用時(shí)。輸出處理器的結(jié)果是分配給項(xiàng)目的最終值。
讓我們看一個(gè)例子來(lái)說(shuō)明如何為特定字段調(diào)用輸入和輸出處理器(同樣適用于任何其他字段):
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)所以會(huì)發(fā)生什么:
值得注意的是,處理器只是可調(diào)用對(duì)象,它們使用要解析的數(shù)據(jù)調(diào)用,并返回解析的值。所以你可以使用任何功能作為輸入或輸出處理器。唯一的要求是它們必須接受一個(gè)(也只有一個(gè))位置參數(shù),這將是一個(gè)迭代器。
注意
輸入和輸出處理器都必須接收一個(gè)迭代器作為它們的第一個(gè)參數(shù)。這些函數(shù)的輸出可以是任何東西。輸入處理器的結(jié)果將附加到包含收集的值(對(duì)于該字段)的內(nèi)部列表(在加載程序中)。輸出處理器的結(jié)果是最終分配給項(xiàng)目的值。
另一件需要記住的事情是,輸入處理器返回的值在內(nèi)部(在列表中)收集,然后傳遞到輸出處理器以填充字段。
最后,但并非最不重要的是,Scrapy自帶一些常用的處理器內(nèi)置的方便。
?
?
聲明項(xiàng)目加載器
?
項(xiàng)目加載器通過(guò)使用類(lèi)定義語(yǔ)法聲明為 Items。這里是一個(gè)例子:
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_out = Join()price_in = MapCompose(unicode.strip)# ...可以看到,輸入處理器使用_in后綴聲明,而輸出處理器使用_out后綴聲明。您還可以使用ItemLoader.default_input_processor和 ItemLoader.default_output_processor屬性聲明默認(rèn)輸入/輸出 處理器。
?
?
聲明輸入和輸出處理器
?
如上一節(jié)所述,輸入和輸出處理器可以在Item Loader定義中聲明,這種方式聲明輸入處理器是很常見(jiàn)的。但是,還有一個(gè)地方可以指定要使用的輸入和輸出處理器:在項(xiàng)目字段 元數(shù)據(jù)中。這里是一個(gè)例子:
import scrapy from scrapy.loader.processors import Join, MapCompose, TakeFirst from w3lib.html import remove_tagsdef 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(),)>>> from scrapy.loader import ItemLoader
>>> il = ItemLoader(item=Product())
>>> il.add_value('name', [u'Welcome to my', u'<strong>website</strong>'])
>>> il.add_value('price', [u'€', u'<span>1000</span>'])
>>> il.load_item()
{'name': u'Welcome to my website', 'price': u'1000'}
輸入和輸出處理器的優(yōu)先級(jí)順序如下:
參見(jiàn):重用和擴(kuò)展項(xiàng)目加載器。
?
?
項(xiàng)目加載器上下文
?
項(xiàng)目加載器上下文是在項(xiàng)目加載器中的所有輸入和輸出處理器之間共享的任意鍵/值的dict。它可以在聲明,實(shí)例化或使用Item Loader時(shí)傳遞。它們用于修改輸入/輸出處理器的行為。
例如,假設(shè)您有一個(gè)parse_length接收文本值并從中提取長(zhǎng)度的函數(shù):
def parse_length(text, loader_context):unit = loader_context.get('unit', 'm')# ... length parsing code goes here ...return parsed_length通過(guò)接受一個(gè)loader_context參數(shù),該函數(shù)顯式地告訴Item Loader它能夠接收一個(gè)Item Loader上下文,因此Item Loader在調(diào)用它時(shí)傳遞當(dāng)前活動(dòng)的上下文,因此處理器功能(parse_length在這種情況下)可以使用它們。
?
有幾種方法可以修改Item Loader上下文值:
- 1. 通過(guò)修改當(dāng)前活動(dòng)的Item Loader上下文(context屬性):
?loader = ItemLoader(product)
?loader.context['unit'] = 'cm' - 2.?On Item Loader實(shí)例化(Item Loader構(gòu)造函數(shù)的關(guān)鍵字參數(shù)存儲(chǔ)在Item Loader上下文中):
?loader = ItemLoader(product, unit='cm') - 3.?On Item Loader聲明,對(duì)于那些支持使用Item Loader上下文實(shí)例化的輸入/輸出處理器。MapCompose是其中之一:
class ProductLoader(ItemLoader):
? ? length_out = MapCompose(parse_length, unit='cm')
?
?
ItemLoader對(duì)象
?
class scrapy.loader.ItemLoader([item, selector, response, ]**kwargs)
返回一個(gè)新的Item Loader來(lái)填充給定的Item。如果沒(méi)有給出項(xiàng)目,則使用中的類(lèi)自動(dòng)實(shí)例化 default_item_class。
當(dāng)使用選擇器或響應(yīng)參數(shù)實(shí)例化時(shí),ItemLoader類(lèi)提供了使用選擇器從網(wǎng)頁(yè)提取數(shù)據(jù)的方便的機(jī)制。
參數(shù):
- item(Item對(duì)象)-項(xiàng)目實(shí)例來(lái)填充用以后調(diào)用 add_xpath(),add_css()或add_value()。
- selector(Selectorobject) - 當(dāng)使用add_xpath()(或。add_css())或replace_xpath() (或replace_css())方法時(shí),從中提取數(shù)據(jù)的選擇器 。
- response(Responseobject) - 用于使用構(gòu)造選擇器的響應(yīng) default_selector_class,除非給出選擇器參數(shù),在這種情況下,將忽略此參數(shù)。
item, selector, response?和 剩余的 關(guān)鍵字參數(shù) 被分配給 Loader上下文(可通過(guò)context屬性訪(fǎng)問(wèn))。
?
?
ItemLoader 實(shí)例有以下方法:
?
get_value(value,* processors,** kwargs )
處理給定value的給定processors和關(guān)鍵字參數(shù)。
可用的關(guān)鍵字參數(shù):
參數(shù): re(str 或compiled regex):一個(gè)正則表達(dá)式extract_regex(),用于使用方法從給定值提取數(shù)據(jù),在處理器之前應(yīng)用
例子:
>>> from scrapy.loader.processors import TakeFirst >>> loader.get_value(u'name: foo', TakeFirst(), unicode.upper, re='name: (.+)') 'FOO`add_value(field_name,value,* processors,** kwargs )
處理,然后添加給value定字段的給定。
該值首先通過(guò)get_value()賦予 processors和kwargs,然后通過(guò) 字段輸入處理器及其結(jié)果追加到為該字段收集的數(shù)據(jù)。如果字段已包含收集的數(shù)據(jù),則會(huì)添加新數(shù)據(jù)。
給定field_name可以是None,在這種情況下可以添加多個(gè)字段的值。并且已處理的值應(yīng)為一個(gè)字段,其中field_name映射到值。
例子:
loader.add_value('name', u'Color TV') loader.add_value('colours', [u'white', u'blue']) loader.add_value('length', u'100') loader.add_value('name', u'name: foo', TakeFirst(), re='name: (.+)') loader.add_value(None, {'name': u'foo', 'sex': u'male'})replace_value(field_name,value,* processors,** kwargs )
類(lèi)似于add_value()但是用新值替換收集的數(shù)據(jù),而不是添加它。
get_xpath(xpath,* processors,** kwargs)
類(lèi)似于ItemLoader.get_value()但接收XPath而不是值,用于從與此相關(guān)聯(lián)的選擇器提取unicode字符串的列表ItemLoader。
參數(shù):
- xpath(str) - 從中??提取數(shù)據(jù)的XPath
- re(str 或compiled regex) - 用于從所選XPath區(qū)域提取數(shù)據(jù)的正則表達(dá)式
例子:
# HTML snippet: <p class="product-name">Color TV</p> loader.get_xpath('//p[@class="product-name"]') # HTML snippet: <p id="price">the price is $1200</p> loader.get_xpath('//p[@id="price"]', TakeFirst(), re='the price is (.*)')add_xpath(field_name,xpath,* processor,** kwargs)
類(lèi)似于ItemLoader.add_value()但接收XPath而不是值,用于從與此相關(guān)聯(lián)的選擇器提取unicode字符串的列表ItemLoader。
見(jiàn) get_xpath() 的 kwargs。
參數(shù):xpath(str) - 從中??提取數(shù)據(jù)的XPath
例子:
# HTML snippet: <p class="product-name">Color TV</p> loader.add_xpath('name', '//p[@class="product-name"]') # HTML snippet: <p id="price">the price is $1200</p> loader.add_xpath('price', '//p[@id="price"]', re='the price is (.*)')replace_xpath(field_name,xpath,* processor,** kwargs)
類(lèi)似于add_xpath()但替換收集的數(shù)據(jù),而不是添加它。
get_css(css,* processors,** kwargs)
類(lèi)似于ItemLoader.get_value()但接收一個(gè)CSS選擇器而不是一個(gè)值,用于從與此相關(guān)的選擇器提取一個(gè)unicode字符串列表ItemLoader。
參數(shù):
- css(str) - 從中??提取數(shù)據(jù)的CSS選擇器
- re(str 或compiled regex) - 用于從所選CSS區(qū)域提取數(shù)據(jù)的正則表達(dá)式
例子:
# HTML snippet: <p class="product-name">Color TV</p> loader.get_css('p.product-name') # HTML snippet: <p id="price">the price is $1200</p> loader.get_css('p#price', TakeFirst(), re='the price is (.*)')add_css(field_name,css,* processors,** kwargs)
類(lèi)似于ItemLoader.add_value()但接收一個(gè)CSS選擇器而不是一個(gè)值,用于從與此相關(guān)的選擇器提取一個(gè)unicode字符串列表ItemLoader。
見(jiàn) get_css()的kwargs。
參數(shù):css(str) - 從中??提取數(shù)據(jù)的CSS選擇器
例子:
# HTML snippet: <p class="product-name">Color TV</p> loader.add_css('name', 'p.product-name') # HTML snippet: <p id="price">the price is $1200</p> loader.add_css('price', 'p#price', re='the price is (.*)')replace_css(field_name,css,* processors,** kwargs )
類(lèi)似于add_css()但替換收集的數(shù)據(jù),而不是添加它。
load_item()
使用目前收集的數(shù)據(jù)填充項(xiàng)目,并返回。收集的數(shù)據(jù)首先通過(guò)輸出處理器,以獲得要分配給每個(gè)項(xiàng)目字段的最終值。
nested_xpath(xpath )
使用xpath選擇器創(chuàng)建嵌套加載器。所提供的選擇器應(yīng)用于與此相關(guān)的選擇器ItemLoader。嵌套裝載機(jī)股份Item 與母公司ItemLoader這么調(diào)用add_xpath(), add_value(),replace_value()等會(huì)像預(yù)期的那樣。
nested_css(css )
使用css選擇器創(chuàng)建嵌套加載器。所提供的選擇器應(yīng)用于與此相關(guān)的選擇器ItemLoader。嵌套裝載機(jī)股份Item 與母公司ItemLoader這么調(diào)用add_xpath(), add_value(),replace_value()等會(huì)像預(yù)期的那樣。
get_collected_values(field_name )
返回給定字段的收集值。
get_output_value(field_name )
返回給定字段使用輸出處理器解析的收集值。此方法根本不填充或修改項(xiàng)目。
get_input_processor(field_name )
返回給定字段的輸入處理器。
get_output_processor(field_name )
返回給定字段的輸出處理器。
?
?
ItemLoader 實(shí)例具有以下屬性:
?
item
Item此項(xiàng)目加載器解析的對(duì)象。
context
此項(xiàng)目Loader 的當(dāng)前活動(dòng)上下文。
default_item_class
Item類(lèi)(或工廠(chǎng)),用于在構(gòu)造函數(shù)中未給出時(shí)實(shí)例化項(xiàng)。
default_input_processor
用于不指定一個(gè)字段的字段的默認(rèn)輸入處理器。
default_output_processor
用于不指定一個(gè)字段的字段的默認(rèn)輸出處理器。
default_selector_class
所使用的類(lèi)構(gòu)造selector的此 ItemLoader,如果只響應(yīng)在構(gòu)造函數(shù)給出。如果在構(gòu)造函數(shù)中給出了選擇器,則忽略此屬性。此屬性有時(shí)在子類(lèi)中被覆蓋。
selector
Selector從中提取數(shù)據(jù)的對(duì)象。它是在構(gòu)造函數(shù)中給出的選擇器,或者是從構(gòu)造函數(shù)中使用的給定的響應(yīng)創(chuàng)建的 default_selector_class。此屬性意味著是只讀的。
?
?
嵌套裝載器
?
當(dāng)解析來(lái)自文檔的子部分的相關(guān)值時(shí),創(chuàng)建嵌套加載器可能是有用的。假設(shè)您從頁(yè)面的頁(yè)腳中提取細(xì)節(jié),看起來(lái)像:
例:
<footer><a class="social" href="http://facebook.com/whatever">Like Us</a><a class="social" href="http://twitter.com/whatever">Follow Us</a><a class="email" href="mailto:whatever@example.com">Email Us</a> </footer>如果沒(méi)有嵌套加載器,則需要為要提取的每個(gè)值指定完整的xpath(或css)。
例:
loader = ItemLoader(item=Item()) # load stuff not in the footer loader.add_xpath('social', '//footer/a[@class = "social"]/@href') loader.add_xpath('email', '//footer/a[@class = "email"]/@href') loader.load_item()相反,您可以使用頁(yè)腳選擇器創(chuàng)建嵌套加載器,并相對(duì)于頁(yè)腳添加值。功能是相同的,但您避免重復(fù)頁(yè)腳選擇器。
例:
loader = ItemLoader(item=Item()) # load stuff not in the footer footer_loader = loader.nested_xpath('//footer') footer_loader.add_xpath('social', 'a[@class = "social"]/@href') footer_loader.add_xpath('email', 'a[@class = "email"]/@href') # no need to call footer_loader.load_item() loader.load_item()您可以任意嵌套加載器,并且可以使用xpath或css選擇器。作為一般的指導(dǎo)原則,當(dāng)他們使你的代碼更簡(jiǎn)單,但不要超越嵌套或使用解析器可能變得難以閱讀使用嵌套加載程序。
?
?
重用和擴(kuò)展項(xiàng)目加載器
?
隨著你的項(xiàng)目越來(lái)越大,越來(lái)越多的爬蟲(chóng),維護(hù)成為一個(gè)根本的問(wèn)題,特別是當(dāng)你必須處理每個(gè)爬蟲(chóng)的許多不同的解析規(guī)則,有很多異常,但也想重用公共處理器。
項(xiàng)目加載器旨在減輕解析規(guī)則的維護(hù)負(fù)擔(dān),同時(shí)不會(huì)失去靈活性,同時(shí)提供了擴(kuò)展和覆蓋它們的方便的機(jī)制。因此,項(xiàng)目加載器支持傳統(tǒng)的Python類(lèi)繼承,以處理特定爬蟲(chóng)(或爬蟲(chóng)組)的差異。
例如,假設(shè)某個(gè)特定站點(diǎn)以三個(gè)短劃線(xiàn)(例如)包含其產(chǎn)品名稱(chēng),并且您不希望最終在最終產(chǎn)品名稱(chēng)中刪除那些破折號(hào)。---Plasma TV---
以下是如何通過(guò)重用和擴(kuò)展默認(rèn)產(chǎn)品項(xiàng)目Loader(ProductLoader)來(lái)刪除這些破折號(hào):
from scrapy.loader.processors import MapCompose from myproject.ItemLoaders import ProductLoaderdef strip_dashes(x):return x.strip('-')class SiteSpecificLoader(ProductLoader):name_in = MapCompose(strip_dashes, ProductLoader.name_in)另一種擴(kuò)展項(xiàng)目加載器可能非常有用的情況是,當(dāng)您有多種源格式,例如XML和HTML。在XML版本中,您可能想要?jiǎng)h除CDATA事件。下面是一個(gè)如何做的例子:
from scrapy.loader.processors import MapCompose from myproject.ItemLoaders import ProductLoader from myproject.utils.xml import remove_cdata class XmlProductLoader(ProductLoader):name_in = MapCompose(remove_cdata, ProductLoader.name_in)這就是你通常擴(kuò)展輸入處理器的方式。
對(duì)于輸出處理器,更常見(jiàn)的是在字段元數(shù)據(jù)中聲明它們,因?yàn)樗鼈兺ǔH依賴(lài)于字段而不是每個(gè)特定站點(diǎn)解析規(guī)則(如輸入處理器)。另請(qǐng)參見(jiàn): 聲明輸入和輸出處理器。
還有許多其他可能的方法來(lái)擴(kuò)展,繼承和覆蓋您的項(xiàng)目加載器,不同的項(xiàng)目加載器層次結(jié)構(gòu)可能更適合不同的項(xiàng)目。Scrapy只提供了機(jī)制; 它不強(qiáng)加任何特定的組織你的Loader集合 - 這取決于你和你的項(xiàng)目的需要。
?
?
可用內(nèi)置處理器
?
即使您可以使用任何可調(diào)用函數(shù)作為輸入和輸出處理器,Scrapy也提供了一些常用的處理器,如下所述。其中一些,像MapCompose(通常用作輸入處理器)組成按順序執(zhí)行的幾個(gè)函數(shù)的輸出,以產(chǎn)生最終的解析值。
下面是所有內(nèi)置處理器的列表:
class scrapy.loader.processors.Identity
最簡(jiǎn)單的處理器,什么都不做。它返回原始值不變。它不接收任何構(gòu)造函數(shù)參數(shù),也不接受Loader上下文。
例:
>>> from scrapy.loader.processors import Identity
>>> proc = Identity()
>>> proc(['one', 'two', 'three'])
['one', 'two', 'three']
class scrapy.loader.processors.TakeFirst
從接收到的值中返回第一個(gè)非空值/非空值,因此它通常用作單值字段的輸出處理器。它不接收任何構(gòu)造函數(shù)參數(shù),也不接受Loader上下文。
例:
>>> from scrapy.loader.processors import TakeFirst
>>> proc = TakeFirst()
>>> proc(['', 'one', 'two', 'three'])
'one'
class scrapy.loader.processors.Join(separator=u' ')
返回與構(gòu)造函數(shù)中給定的分隔符聯(lián)接的值,默認(rèn)為。它不接受加載器上下文。u' '
當(dāng)使用默認(rèn)分隔符時(shí),此處理器相當(dāng)于以下功能: u' '.join
例子:
>>> from scrapy.loader.processors import Join
>>> proc = Join()
>>> proc(['one', 'two', 'three'])
u'one two three'
>>> proc = Join('<br>')
>>> proc(['one', 'two', 'three'])
u'one<br>two<br>three'
class scrapy.loader.processors.Compose(*functions, **default_loader_context)
由給定函數(shù)的組合構(gòu)成的處理器。這意味著該處理器的每個(gè)輸入值都被傳遞給第一個(gè)函數(shù),并且該函數(shù)的結(jié)果被傳遞給第二個(gè)函數(shù),依此類(lèi)推,直到最后一個(gè)函數(shù)返回該處理器的輸出值。
默認(rèn)情況下,停止進(jìn)程N(yùn)one值。可以通過(guò)傳遞關(guān)鍵字參數(shù)來(lái)更改此行為stop_on_none=False。
例:
>>> from scrapy.loader.processors import Compose
>>> proc = Compose(lambda v: v[0], str.upper)
>>> proc(['hello', 'world'])
'HELLO'
每個(gè)功能可以可選地接收l(shuí)oader_context參數(shù)。對(duì)于那些處理器,這個(gè)處理器將通過(guò)該參數(shù)傳遞當(dāng)前活動(dòng)的Loader上下文。
在構(gòu)造函數(shù)中傳遞的關(guān)鍵字參數(shù)用作傳遞給每個(gè)函數(shù)調(diào)用的默認(rèn)Loader上下文值。但是,傳遞給函數(shù)的最后一個(gè)Loader上下文值將被當(dāng)前可用該屬性訪(fǎng)問(wèn)的當(dāng)前活動(dòng)Loader上下文ItemLoader.context() 覆蓋。
class scrapy.loader.processors.MapCompose(*functions, **default_loader_context)
與處理器類(lèi)似,由給定功能的組成構(gòu)成的Compose處理器。與此處理器的區(qū)別在于內(nèi)部結(jié)果在函數(shù)之間傳遞的方式,如下所示:
該處理器的輸入值被迭代,并且第一函數(shù)被應(yīng)用于每個(gè)元素。這些函數(shù)調(diào)用的結(jié)果(每個(gè)元素一個(gè))被連接以構(gòu)造新的迭代,然后用于應(yīng)用??第二個(gè)函數(shù),等等,直到最后一個(gè)函數(shù)被應(yīng)用于收集的值列表的每個(gè)值遠(yuǎn)。最后一個(gè)函數(shù)的輸出值被連接在一起以產(chǎn)生該處理器的輸出。
每個(gè)特定函數(shù)可以返回值或值列表,這些值通過(guò)應(yīng)用于其他輸入值的相同函數(shù)返回的值列表展平。函數(shù)也可以返回None,在這種情況下,該函數(shù)的輸出將被忽略,以便在鏈上進(jìn)行進(jìn)一步處理。
此處理器提供了一種方便的方法來(lái)組合只使用單個(gè)值(而不是iterables)的函數(shù)。由于這個(gè)原因, MapCompose處理器通常用作輸入處理器,因?yàn)閿?shù)據(jù)通常使用選擇器的 extract()方法提取,選擇器返回unicode字符串的列表。
下面的例子應(yīng)該說(shuō)明它是如何工作的:
>>> def filter_world(x):
... ? ? return None if x == 'world' else x
...
>>> from scrapy.loader.processors import MapCompose
>>> proc = MapCompose(filter_world, unicode.upper)
>>> proc([u'hello', u'world', u'this', u'is', u'scrapy'])
[u'HELLO, u'THIS', u'IS', u'SCRAPY']
與Compose處理器一樣,函數(shù)可以接收Loader上下文,并且構(gòu)造函數(shù)關(guān)鍵字參數(shù)用作默認(rèn)上下文值。有關(guān)Compose更多信息,請(qǐng)參閱 處理器。
class scrapy.loader.processors.SelectJmes(json_path)
使用提供給構(gòu)造函數(shù)的json路徑查詢(xún)值,并返回輸出。需要運(yùn)行jmespath(https://github.com/jmespath/jmespath.py)。該處理器一次只需要一個(gè)輸入。
例:
>>> from scrapy.loader.processors import SelectJmes, Compose, MapCompose
>>> proc = SelectJmes("foo") #for direct use on lists and dictionaries
>>> proc({'foo': 'bar'})
'bar'
>>> proc({'foo': {'bar': 'baz'}})
{'bar': 'baz'}
?
使用Json:
>>> import json
>>> proc_single_json_str = Compose(json.loads, SelectJmes("foo"))
>>> proc_single_json_str('{"foo": "bar"}')
u'bar'
>>> proc_json_list = Compose(json.loads, MapCompose(SelectJmes('foo')))
>>> proc_json_list('[{"foo":"bar"}, {"baz":"tar"}]')
[u'bar']
?
?
?
總結(jié)
以上是生活随笔為你收集整理的Scrapy-Item Loaders(项目加载器)的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: Scrapy源码阅读分析_3_核心组件
- 下一篇: Linux-----diff命令