Itemローダー¶
Itemローダーは、抽出したデータを Item に投入するための便利なメカニズムを提供します。Itemは独自の辞書ライクなAPIを使用して作成できますが、Itemローダーは抽出前のデータを解析するなどの一般的なタスクを自動化することで、スクレイピングの過程でデータを取り込むための便利なAPIを提供します。
言い換えれば、 Item は抽出されたデータのコンテナを提供し、Itemローダーはそのコンテナに投入するためのメカニズムを提供します。
Itemローダーは、Spiderまたはソースフォーマット(HTML、XMLなど)のいずれかで、メンテナンス地獄にならないように、フィールドの解析ルールを拡張・上書きするための柔軟で効率的で簡単なメカニズムを提供するように設計されています。
Itemローダーを使用してItemを設定する¶
Itemローダーを使用するには、まずそれをインスタンス化する必要があります。dictライクなオブジェクト(Itemやdictなど)でインスタンス化することも、 ItemLoader.default_item_class
属性で指定されたItemクラスを使用してItemローダーのコンストラクタでItemを自動的にインスタンス化することもできます。
次に Selectors を使用してItemローダーに値を収集します。同じItemフィールドに複数の値を追加可能で、Itemローダーでは適切な関数を使用してそれらの値を「結合」する方法があります。
Itemの章 で宣言された Product Item を使用して、 Spider でItemローダーを使う一般的な方法を以下に示します。
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()
コードをざっと眺めてみると、XPathでページ内の2箇所から name
フィールドが抽出されていることがわかります。
//div[@class="product_name"]
//div[@class="product_title"]
つまり、 add_xpath()
メソッドを使用して、XPathで2箇所からデータを抽出しています。これは name
フィールドに割り当てられるデータです。
その後、 price
フィールドと stock
フィールド( add_css()
メソッドでCSSセレクタを使用)に同様の呼び出しがされ、最後に last_update
フィールドに add_value()
メソッドを使用してリテラル値( today
)が直接設定されます。
最後に、すべてのデータが収集されると、 ItemLoader.load_item()
メソッドが呼び出され、 add_xpath()
, add_css()
および add_value()
の呼び出しで抽出されたデータがItemに格納されます。
入力および出力プロセッサ¶
Itemローダーには、Itemの各フィールドに入力プロセッサと出力プロセッサが1つずつ含まれています。入力プロセッサは、 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
フィールドの 入力プロセッサ に渡されます。入力プロセッサの結果は収集され、Itemローダーに保持されます(しかし、Itemにはまだ割り当てられません)。xpath2
からのデータが抽出され、(1)と同じ入力プロセッサを通過します。入力プロセッサの結果が存在する場合は、(1)で収集されたデータに追加されます。- このケースは前のものと似ていますが、データが
css
CSSセレクタから抽出され、(1)と(2)で使用されたものと同じ入力プロセッサを通過します。入力プロセッサの結果が存在する場合は、(1)および(2)で収集されたデータに追加されます - このケースも前のものと似ていますが、収集する値がXPath式やCSSセレクタから抽出される代わりに直接割り当てられる点が異なります。ただし、値は引き続き入力プロセッサを通過します。この場合の値はiterableではありませんが、入力プロセッサは常にiterableを受け取るので、値は入力プロセッサに渡す前に単一要素のiterableに変換されます。
- ステップ(1)(2)(3)(4)で収集されたデータは、
name
フィールドの 出力プロセッサ を通過します。出力プロセッサの結果は、Itemのname
フィールドに割り当てられる値です。
プロセッサは呼び出し可能なオブジェクトであり、パース対象のデータで呼び出され、パースされた値を返すだけであることに注意してください。したがって、入力または出力プロセッサとして任意の関数を使用できます。唯一の条件は、イテレータである1つの位置引数を受け入れる必要があることです。
注釈
入力プロセッサと出力プロセッサのどちらも、最初の引数としてイテレータを受け取る必要があります。これらの関数の出力は何でもかまいません。入力プロセッサの結果は、そのフィールドのために収集された値を含むローダー内の内部リストに追加されます。出力プロセッサの結果は、最終的にItemに割り当てられる値です。
プレーンな関数をプロセッサとして使用する場合は、最初の引数として self
を受け取るようにしてください。
def lowercase_processor(self, values):
for v in values:
yield v.lower()
class MyItemLoader(ItemLoader):
name_in = lowercase_processor
これは、関数をクラスの属性として割り当てるとメソッドになり、呼び出されるときに最初の引数としてインスタンスが渡されるためです。詳細については、 stackoverflowのこの回答 を参照してください。
もうひとつ留意すべきことは、入力プロセッサから返された値が内部的にリストに集められ、フィールドにデータを投入するために出力プロセッサに渡されることです。
最後に、Scrapyには、利便性のため 一般的に使用されるプロセッサ がいくつかビルトインされています。
Itemローダーの宣言¶
Itemローダーは、クラス定義構文を使用してItemのように宣言されます。次に例を示します。
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
属性を使用して、デフォルトの入出力プロセッサを宣言することもできます。
入力プロセッサおよび出力プロセッサの宣言¶
前のセクションで見たように、入出力プロセッサはItemローダーの定義で宣言することができ、このように入力プロセッサを宣言することは非常に一般的です。しかしもう1つ、 Itemフィールド メタデータに使用する入力プロセッサおよび出力プロセッサを指定することもできます。次に例を示します。
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(),
)
>>> 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'}
入力プロセッサと出力プロセッサの優先順位は次のとおりです。
- Item ローダーのフィールド固有の属性:
field_in
およびfield_out
(最も優先度が高い) - フィールドメタデータ(
input_processor
およびoutput_processor
キー) - Itemローダーのデフォルト:
ItemLoader.default_input_processor()
およびItemLoader.default_output_processor()
(最も優先度が低い)
参照: Itemローダーの再利用と拡張
Itemローダーコンテキスト¶
Itemローダーコンテキストは、Itemローダー内のすべての入出力プロセッサで共有される任意のキー/値のdictです。これは、Itemローダーの宣言、インスタンス化、または使用時に渡すことが可能で、入出力プロセッサの動作を変更するために使用されます。
たとえば、テキストを受け取りそこから長さを抽出する関数 parse_length
があるとします。
def parse_length(text, loader_context):
unit = loader_context.get('unit', 'm')
# ... length parsing code goes here ...
return parsed_length
loader_context
引数を指定することによって、関数がItemローダーコンテキストを受け取ることを明示的にItemローダーに伝えます。そして、Itemローダーは呼び出し時に現在アクティブなコンテキストを渡し、プロセッサ関数(この場合は parse_length
)はそれを使うことができます。
Itemローダーコンテキストの値を変更する方法はいくつかあります。
現在アクティブなItemローダーコンテキスト(
context
属性)の変更時。loader = ItemLoader(product) loader.context['unit'] = 'cm'
Itemローダーのインスタンス化時(コンストラクタのキーワード引数がItemローダーコンテキストに格納されます)。
loader = ItemLoader(product, unit='cm')
Itemローダーの宣言時。Itemローダーコンテキスト付きでインスタンス化をサポートする入出力プロセッサ用に宣言されます。
MapCompose
はその1つです。class ProductLoader(ItemLoader): length_out = MapCompose(parse_length, unit='cm')
Itemローダーオブジェクト¶
-
class
scrapy.loader.
ItemLoader
([item, selector, response, ]**kwargs)¶ 指定されたItemを取り込むための新しいItemローダーを返します。Itemが指定されていない場合は、
default_item_class
のクラスを使用して自動的にインスタンス化されます。selector または response パラメータを使用してインスタンス化すると、
ItemLoader
クラスは セレクタ を使用してWebページからデータを抽出する便利なメカニズムを提供します。パラメータ: - item (
Item
object) --add_xpath()
,add_css()
,add_value()
を使用して設定するItemインスタンス。 - selector (
Selector
object) --add_xpath()
,add_css()
メソッドまたはreplace_xpath()
,replace_css()
メソッドを使用してデータを抽出するときのセレクタ。 - response (
Response
object) --default_selector_class
を使用してセレクタを構成するために使用されたレスポンス。selector引数が指定されていない場合は、この引数は無視されます。
item, selector, responseおよび残りのキーワード引数は、(
context
属性を通してアクセス可能な)ローダーコンテキストに割り当てられます。ItemLoader
インスタンスには、次のメソッドがあります。-
get_value
(value, *processors, **kwargs)¶ processors
とキーワードの引数でvalue
を処理します。使用可能なキーワード引数:
パラメータ: re (str or compiled regex) -- extract_regex()
メソッドを使用して与えられた値からデータを抽出するための正規表現。processorsの前に適用されます。例:
>>> 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
を処理して追加します。このvalueは、最初に
processors
とkwargs
を与えることによってget_value()
に渡され、次に フィールドの入力プロセッサ を通過し、結果がそのフィールド用に収集されたデータに追加されます。フィールドにすでに収集されたデータが含まれている場合は、新しいデータが追加されます。field_name
はNone
にすることができます。その場合は複数のフィールドの値を追加できますが、valueは、field_nameと値がマップされたdictでなければなりません。例:
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)¶ add_value()
と似ていますが、収集されたデータを追加するのではなく新しい値に置き換えます。
-
get_xpath
(xpath, *processors, **kwargs)¶ ItemLoader.get_value()
と同様ですが、値の代わりにXPathを受け取ります。これは、このItemLoader
に関連付けられたセレクタからUnicode文字列のリストを抽出するために使用されます。パラメータ: - xpath (str) -- データを抽出するXPath
- re (str or compiled regex) -- XPathで選択された領域からデータを抽出するために使用される正規表現
例:
# 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, *processors, **kwargs)¶ ItemLoader.add_value()
と同様ですが、値の代わりにXPathを受け取ります。これは、このItemLoader
に関連付けられたセレクタからUnicode文字列のリストを抽出するために使用されます。kwargs
についてはget_xpath()
を参照してください。パラメータ: xpath (str) -- データを抽出する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, *processors, **kwargs)¶ add_xpath()
と似ていますが、収集されたデータを追加する代わりに置き換えます。
-
get_css
(css, *processors, **kwargs)¶ ItemLoader.get_value()
と同様ですが、値の代わりにCSSセレクタを受け取ります。このセレクタは、このItemLoader
に関連付けられたセレクタからUnicode文字列のリストを抽出するために使用されます。パラメータ: - css (str) -- データを抽出するCSSセレクタ
- re (str or compiled regex) -- CSSセレクタで選択された領域からデータを抽出するために使用される正規表現
例:
# 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)¶ ItemLoader.add_value()
と同様ですが、値の代わりにCSSセレクタを受け取ります。このセレクタは、このItemLoader
に関連付けられたセレクタからUnicode文字列のリストを抽出するために使用されます。kwargs
についてはget_css()
を参照してください。パラメータ: css (str) -- データを抽出する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 (.*)')
-
nested_xpath
(xpath)¶ XPathセレクタでネストされたローダーを作成します。指定されたセレクタは、この
ItemLoader
に関連付けられたセレクタに対して相対的に適用されます。ネストされたローダーは親ItemLoader
とItem
を共有するため、add_xpath()
,add_value()
,replace_value()
などの呼び出しは期待どおりに動作します。
-
nested_css
(css)¶ CSSセレクタでネストされたローダーを作成します。指定されたセレクタは、この
ItemLoader
に関連付けられたセレクタに対して相対的に適用されます。ネストされたローダーは親ItemLoader
とItem
を共有するため、add_xpath()
,add_value()
,replace_value()
などの呼び出しは期待どおりに動作します。
-
get_collected_values
(field_name)¶ 指定されたフィールドの収集された値を返します。
-
get_output_value
(field_name)¶ 指定されたフィールドに対して、出力プロセッサを使用してパースされた収集値を返します。このメソッドはItemを作成したり変更したりしません。
-
get_input_processor
(field_name)¶ 指定されたフィールドの入力プロセッサを返します。
-
get_output_processor
(field_name)¶ 指定されたフィールドの出力プロセッサを返します。
ItemLoader
インスタンスには、以下の属性があります。-
default_item_class
¶ コンストラクタで指定されていないときに項目をインスタンス化するために使用されるItemクラス(またはファクトリ)。
-
default_input_processor
¶ 入力プロセッサが指定されていないフィールドに使用するデフォルトの入力プロセッサ。
-
default_output_processor
¶ 出力プロセッサが指定されていないフィールドに使用するデフォルトの出力プロセッサ。
-
default_selector_class
¶ コンストラクタでresponseのみが与えられている場合、この
ItemLoader
のselector
を構築するために使用されるクラスです。セレクタがコンストラクタで指定されている場合、この属性は無視されます。この属性はサブクラスでオーバーライドされることもあります。
-
selector
¶ データを抽出する
Selector
オブジェクト。これは、コンストラクタで指定されたセレクタか、default_selector_class
を使用してコンストラクタで指定されたresponseから作成されたセレクタです。この属性は読み取り専用です。
- item (
ネストされたローダー¶
関連する値をドキュメントのサブセクションから解析するときは、ネストされたローダーを作成すると便利です。例えば、次のようなページのフッターから詳細を抽出するとします。
例:
<footer>
<a class="social" href="https://facebook.com/whatever">Like Us</a>
<a class="social" href="https://twitter.com/whatever">Follow Us</a>
<a class="email" href="mailto:whatever@example.com">Email Us</a>
</footer>
ネストされたローダーがなければ、抽出するそれぞれの値に対して完全な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()
代わりに、footerセレクタでネストされたローダーを作成し、フッターを基準にして値を追加することができます。機能としては同じですが、footerセレクタの繰り返しを避けることが可能です。
例:
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セレクタを使用して動きます。一般的なガイドラインとして、ネストされたローダーを使用するとコードが単純になりますが、極端にネストするとパーサーが読みにくくなることがあります。
Itemローダーの再利用と拡張¶
プロジェクトが大きくなり、多くのSpiderが動くようになると、メンテナンスが根本的な問題になります。特に、Spiderごとにさまざまな解析ルールを処理しなければならないときは、多くの例外があり、しかし一般的なプロセッサを再利用したい要望があります。
Itemローダーは、柔軟性を失うことなくルール解析のメンテナンスの負担を軽減すると同時に、それらを拡張したり上書きするための便利なメカニズムを提供するように設計されています。この理由から、Itemローダーは特定のSpider(またはSpiderのグループ)の違いに対処するために従来のPythonクラス継承をサポートしています。
たとえば、特定のサイトが製品名を3つのダッシュ(例:: ---Plasma TV---
)で囲んでいて、最終的に製品名にはこれらのダッシュをスクレイピングしたくないとします。
デフォルトのProduct Itemローダー (ProductLoader
) を再利用して拡張することによって、これらのダッシュを削除する方法は次のとおりです。
from scrapy.loader.processors import MapCompose
from myproject.ItemLoaders import ProductLoader
def strip_dashes(x):
return x.strip('-')
class SiteSpecificLoader(ProductLoader):
name_in = MapCompose(strip_dashes, ProductLoader.name_in)
Itemローダーを拡張することが役に立つもう1つのケースは、複数のソースフォーマット(XMLやHTMLなど)がある場合です。XMLバージョンでは、 CDATA
を削除したいかも知れません。この例を次に示します。
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)
これが入力プロセッサを拡張する通常の方法です。
出力プロセッサに関しては、入力プロセッサとは違い、通常はフィールドにのみ依存し、サイトの特定のパースルールには依存しないので、フィールドメタデータで宣言する方が一般的です。 入力プロセッサおよび出力プロセッサの宣言 を参照してください。
Itemローダーを拡張、継承、オーバーライドする方法は他にもたくさんあります。また、プロジェクトごとに適したItemローダーの階層は異なるかもしれません。Scrapyはメカニズムを提供するだけです。ローダーの特定の組み立て方を強制するものではありません。それはあなたとプロジェクトのニーズによって変わります。
使用可能なビルトインプロセッサ¶
呼び出し可能ならばどんな関数も入出力プロセッサとして使用することができますが、Scrapyは一般的に使用されるいくつかのプロセッサを提供しています。これについては後述します。 MapCompose
(通常は入力プロセッサとして使用される)などは、最終的にパースされた値を生成するために、いくつかの関数を順番に実行して出力を構成します。
すべての組み込みプロセッサの一覧は次のとおりです。
-
class
scrapy.loader.processors.
Identity
¶ 最も単純なプロセッサ。何もしません。元の値をそのまま返します。コンストラクタ引数を受け取らず、ローダーコンテキストも受け入れません。
例:
>>> from scrapy.loader.processors import Identity >>> proc = Identity() >>> proc(['one', 'two', 'three']) ['one', 'two', 'three']
-
class
scrapy.loader.processors.
TakeFirst
¶ 受け取った値から、nullでもなく空でもない最初の値を返します。したがって、通常、単一値フィールドの出力プロセッサとして使用されます。コンストラクタ引数を受け取らず、ローダーコンテキストも受け入れません。
例:
>>> from scrapy.loader.processors import TakeFirst >>> proc = TakeFirst() >>> proc(['', 'one', 'two', 'three']) 'one'
-
class
scrapy.loader.processors.
Join
(separator=u' ')¶ コンストラクタで指定されたセパレータで連結された値を返します。デフォルトは
u' '
です。ローダーコンテキストは受け付けません。デフォルトのセパレータを使用する場合、このプロセッサは
u' '.join
と同等です。例:
>>> from scrapy.loader.processors import Join >>> proc = Join() >>> proc(['one', 'two', 'three']) 'one two three' >>> proc = Join('<br>') >>> proc(['one', 'two', 'three']) 'one<br>two<br>three'
-
class
scrapy.loader.processors.
Compose
(*functions, **default_loader_context)¶ 与えられた関数の構成から合成されるプロセッサ。このプロセッサの各入力値が最初の関数に渡され、その関数の結果が2番目の関数に渡され、最後の関数の結果がこのプロセッサの出力値となります。
デフォルトでは
None
の値で処理を停止します。この動作は、キーワード引数stop_on_none=False
を渡すことで変更できます。例:
>>> from scrapy.loader.processors import Compose >>> proc = Compose(lambda v: v[0], str.upper) >>> proc(['hello', 'world']) 'HELLO'
各関数は、オプションで
loader_context
パラメータを受け取ることができます。そうすると、このプロセッサは現在アクティブな ローダーコンテキスト をそのパラメータで渡します。コンストラクタで渡されるキーワード引数は、各関数に渡されるデフォルトのローダーコンテキスト値として使用されます。ただし、最終的に関数に渡されローダーコンテキスト値は、
ItemLoader.context()
属性を介してアクセス可能な現在アクティブなローダーコンテキストでオーバーライドされます。
-
class
scrapy.loader.processors.
MapCompose
(*functions, **default_loader_context)¶ Compose
プロセッサと同様に、与えられた関数の構成から合成されるプロセッサ。違いは、内部の結果が関数間で受け渡される方法です。このプロセッサの入力値が 反復 され、各要素に最初の関数が適用されます。これらの関数呼び出しの結果(各要素に1つずつ)は連結されて新しいiterableを生成し、次にそれを使用して2番目の関数を適用します。そうして収集されたリストの各値が、最後の関数まで適用されます。最後の関数の出力値は、このプロセッサの出力を生成するために連結されます。
それぞれの関数は値または値のリストを返すことができ、これは他の入力値に適用された同じ関数によって返される値のリストで平坦化されます。関数は
None
を返すこともできます。その場合、その関数の出力に続くチェーン処理は無視されます。このプロセッサは(iterableではなく)単一の値でしか機能しない関数を合成する便利な方法を提供します。このため、
MapCompose
プロセッサは通常、入力プロセッサとして使用されます。データは セレクタ のextract()
メソッドを使用して抽出されることが多く、Unicode文字列のリストをすためです。どのように動作するかを明確にした例を示します。
>>> def filter_world(x): ... return None if x == 'world' else x ... >>> from scrapy.loader.processors import MapCompose >>> proc = MapCompose(filter_world, str.upper) >>> proc(['hello', 'world', 'this', 'is', 'scrapy']) ['HELLO, 'THIS', 'IS', 'SCRAPY']
Composeプロセッサと同様に、関数はローダーコンテキストを受け取ることができ、コンストラクタのキーワード引数はデフォルトのコンテキスト値として使用されます。詳細については、
Compose
プロセッサを参照してください。
-
class
scrapy.loader.processors.
SelectJmes
(json_path)¶ コンストラクタに渡されたJSONパスを使用して値を照会し、出力を返します。実行するにはjmespath (https://github.com/jmespath/jmespath.py) が必要です。このプロセッサは、一度に1つの入力のみを受け取ります。
例:
>>> 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"}') 'bar' >>> proc_json_list = Compose(json.loads, MapCompose(SelectJmes('foo'))) >>> proc_json_list('[{"foo":"bar"}, {"baz":"tar"}]') ['bar']