Scrapy-item-loaders
スクレイピー-アイテムローダー
説明
アイテムローダーは、Webサイトからスクレイピングされたアイテムを埋める便利な方法を提供します。
アイテムローダーの宣言
アイテムローダーの宣言はアイテムのようなものです。
たとえば-
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
上記のコードでは、入力プロセッサは _in サフィックスを使用して宣言され、出力プロセッサは _out サフィックスを使用して宣言されていることがわかります。
*ItemLoader.default_input_processor* および *ItemLoader.default_output_processor* 属性は、デフォルトの入出力プロセッサーを宣言するために使用されます。
アイテムローダーを使用してアイテムを作成する
アイテムローダーを使用するには、最初にdictのようなオブジェクトでインスタンス化するか、アイテムが ItemLoader.default_item_class 属性で指定されたアイテムクラスを使用するオブジェクトなしでインスタンス化します。
- セレクターを使用して、アイテムローダーに値を収集できます。
- 同じアイテムフィールドにさらに値を追加できます。アイテムローダーは、適切なハンドラーを使用してこれらの値を追加します。
次のコードは、アイテムローダーを使用してアイテムがどのように読み込まれるかを示しています-
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()
上記に示すように、* add_xpath()メソッドを使用して *title フィールドが抽出される2つの異なるXPathがあります-
1.//div[@class = "product_title"]
2.//div[@class = "product_name"]
その後、同様の要求が desc フィールドに使用されます。 サイズデータは* add_css()メソッドを使用して抽出され、 *last_updated は* add_value()*メソッドを使用して値「昨日」で埋められます。
すべてのデータが収集されたら、* ItemLoader.load_item()メソッドを呼び出します。このメソッドは、 add_xpath()、 add_css()、および add_value()*メソッドを使用して抽出されたデータで満たされたアイテムを返します。
入出力プロセッサー
アイテムローダーの各フィールドには、1つの入力プロセッサと1つの出力プロセッサが含まれています。
- データが抽出されると、入力プロセッサはそれを処理し、その結果はItemLoaderに保存されます。
- 次に、データを収集した後、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 *-タイトルのデータがxpath1から抽出され、入力プロセッサを介して渡され、その結果が収集されてItemLoaderに保存されます。
- 行2 *-同様に、タイトルはxpath2から抽出され、同じ入力プロセッサを通過し、その結果は[1]で収集されたデータに追加されます。
- 行3 *-タイトルはcssセレクターから抽出され、同じ入力プロセッサーを通過し、[1]および[2]について収集されたデータに結果が追加されます。
- 行4 *-次に、値 "demo"が割り当てられ、入力プロセッサに渡されます。
- 行5 *-最後に、データはすべてのフィールドから内部的に収集され、出力プロセッサに渡され、最終値がアイテムに割り当てられます。
入力および出力プロセッサの宣言
入力および出力プロセッサは、ItemLoader定義で宣言されています。 これとは別に、 Item Field メタデータで指定することもできます。
たとえば-
import scrapy
from scrapy.loader.processors import Join, MapCompose, TakeFirst
from w3libl 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'}
アイテムローダーコンテキスト
アイテムローダーコンテキストは、入力および出力プロセッサ間で共有される任意のキー値の辞書です。
たとえば、_parse_length_関数があると仮定します-
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引数を受け取ることにより、Item LoaderにItem Loaderコンテキストを受け取ることができることを伝えます。 アイテムローダーのコンテキストの値を変更するにはいくつかの方法があります-
- 現在アクティブなアイテムローダーコンテキストを変更する-
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)
次の表は、ItemLoaderオブジェクトのパラメータを示しています-
Sr.No | Parameter & Description |
---|---|
1 |
item これは、add_xpath()、add_css()、またはadd_value()を呼び出して入力するアイテムです。 |
2 |
selector Webサイトからデータを抽出するために使用されます。 |
3 |
response default_selector_classを使用してセレクターを構築するために使用されます。 |
次の表は、ItemLoaderオブジェクトのメソッドを示しています-
Sr.No | Method & Description | Example |
---|---|---|
1 |
get_value(value, *processors, **kwargs) 指定されたプロセッサとキーワード引数により、値はget_value()メソッドによって処理されます。 |
|
2 |
add_value(field_name, value, *processors, **kwargs) 値を処理し、フィールド入力プロセッサを通過する前にプロセッサとキーワード引数を与えることにより、get_valueを介して最初に渡されるフィールドに追加します。 |
|
3 |
replace_value(field_name, value, *processors, **kwargs) 収集されたデータを新しい値に置き換えます。 |
|
4 |
get_xpath(xpath, *processors, **kwargs) _XPath_を受け取ることでプロセッサとキーワード引数を与えることでUnicode文字列を抽出するために使用されます。 |
|
5 |
add_xpath(field_name, xpath, *processors, **kwargs) Unicode文字列を抽出するフィールドへの_XPath_を受け取ります。 |
|
6 |
replace_xpath(field_name, xpath, *processors, **kwargs) サイトからの_XPath_を使用して、収集されたデータを置き換えます。 |
|
7 |
get_css(css, *processors, **kwargs) Unicode文字列の抽出に使用されるCSSセレクターを受け取ります。 |
|
8 |
add_css(field_name, css, *processors, **kwargs) add_value()メソッドに似ていますが、CSSセレクターをフィールドに追加する点が1つ異なります。 |
|
9 |
replace_css(field_name, css, *processors, **kwargs) CSSセレクターを使用して、抽出されたデータを置き換えます。 |
|
10 |
load_item() データが収集されると、このメソッドはアイテムに収集されたデータを入れて返します。 |
|
11 |
nested_xpath(xpath) XPathセレクターでネストされたローダーを作成するために使用されます。 |
|
12 |
nested_css(css) CSSセレクターでネストされたローダーを作成するために使用されます。 |
|
次の表は、ItemLoaderオブジェクトの属性を示しています-
Sr.No | Attribute & Description |
---|---|
1 |
item これは、アイテムローダーが解析を実行するオブジェクトです。 |
2 |
context アクティブなのは、アイテムローダーの現在のコンテキストです。 |
3 |
default_item_class コンストラクタで指定されていない場合、アイテムを表すために使用されます。 |
4 |
default_input_processor default_input_processorsが使用されるのは、入力プロセッサを指定しないフィールドのみです。 |
5 |
default_output_processor default_output_processorsが使用されるのは、出力プロセッサを指定しないフィールドのみです。 |
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:[email protected]">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()
アイテムローダーの再利用と拡張
アイテムローダーは、プロジェクトがより多くのスパイダーを取得するときに根本的な問題となるメンテナンスを軽減するように設計されています。
たとえば、サイトの製品名が3つのダッシュで囲まれていると仮定します(例: --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)
利用可能な組み込みプロセッサ
以下は、一般的に使用される組み込みプロセッサの一部です-
クラスscrapy.loader.processors.Identity
変更せずに元の値を返します。 たとえば-
>>> from scrapy.loader.processors import Identity
>>> proc = Identity()
>>> proc(['a', 'b', 'c'])
['a', 'b', 'c']
クラス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.Compose(* functions、** default_loader_context)
これは、各入力値が最初の関数に渡されるプロセッサによって定義され、その関数の結果は2番目の関数に渡され、ast関数が最終値を出力として返すまで続きます。
たとえば-
>>> from scrapy.loader.processors import Compose
>>> proc = Compose(lambda v: v[0], str.upper)
>>> proc(['python', 'scrapy'])
'PYTHON'
class scrapy.loader.processors.MapCompose(* functions、** default_loader_context)
入力値が反復され、最初の関数が各要素に適用されるプロセッサです。 次に、これらの関数呼び出しの結果が連結されて新しい反復可能オブジェクトが作成され、それが最後の関数まで2番目の関数などに適用されます。
たとえば-
>>> def filter_scrapy(x):
return None if x == 'scrapy' else x
>>> from scrapy.loader.processors import MapCompose
>>> proc = MapCompose(filter_scrapy, unicode.upper)
>>> proc([u'hi', u'everyone', u'im', u'pythonscrapy'])
[u'HI, u'IM', u'PYTHONSCRAPY']
クラス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']