文章目錄
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
從文檔的子部分分析相關值時,創建嵌套加載器可能很有用。假設您正在從一個頁面的頁腳提取細節。