Scrapy-item-loaders

提供:Dev Guides
移動先:案内検索

スクレイピー-アイテムローダー

説明

アイテムローダーは、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()メソッドによって処理されます。

>>> 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)

収集されたデータを新しい値に置き換えます。

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_を受け取ることでプロセッサとキーワード引数を与えることでUnicode文字列を抽出するために使用されます。

# HTML code: <div class = "item-name">DVD</div>
loader.get_xpath("//div[@class =
'item-name']")

# HTML code: <div id = "length">the length is
45cm</div>
loader.get_xpath("//div[@id = 'length']", TakeFirst(),
re = "the length is (.*)")
5

add_xpath(field_name, xpath, *processors, **kwargs)

Unicode文字列を抽出するフィールドへの_XPath_を受け取ります。

# 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_を使用して、収集されたデータを置き換えます。

# HTML code: <div class = "item-name">DVD</div>
loader.replace_xpath('name', '

# HTML code: <div id = "length">the length is
 45cm</div>
loader.replace_xpath('length', '
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セレクターをフィールドに追加する点が1つ異なります。

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セレクターを使用して、抽出されたデータを置き換えます。

loader.replace_css('name', 'div.item-name')
loader.replace_css('length', 'div#length',
 re = 'the length is (.*)')
10

load_item()

データが収集されると、このメソッドはアイテムに収集されたデータを入れて返します。

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セレクターでネストされたローダーを作成するために使用されます。

loader = ItemLoader(item = Item())
loader.add_xpath('social', '
a[@class = "social"]/@href')
loader.add_xpath('email', '
a[@class = "email"]/@href')
12

nested_css(css)

CSSセレクターでネストされたローダーを作成するために使用されます。

loader = ItemLoader(item = Item())
loader.add_css('social', 'a[@class = "social"]/@href')
loader.add_css('email', 'a[@class = "email"]/@href')

次の表は、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']