Scrapy - ładowarki przedmiotów
Opis
Moduły ładujące elementy zapewniają wygodny sposób wypełniania elementów, które są usuwane ze stron internetowych.
Deklarowanie programów ładujących przedmioty
Deklaracja osób ładujących przedmioty jest jak przedmioty.
Na przykład -
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
W powyższym kodzie widać, że procesory wejściowe są deklarowane przy użyciu _in przyrostek i procesory wyjściowe są deklarowane przy użyciu _out przyrostek.
Plik ItemLoader.default_input_processor i ItemLoader.default_output_processor atrybuty są używane do deklarowania domyślnych procesorów wejścia / wyjścia.
Używanie modułów ładowania przedmiotów do wypełniania pozycji
Aby użyć modułu ładującego elementy, najpierw utwórz instancję z obiektem podobnym do dict lub bez obiektu, w którym element używa klasy Item określonej w ItemLoader.default_item_class atrybut.
Możesz użyć selektorów, aby zebrać wartości do modułu ładowania przedmiotów.
Możesz dodać więcej wartości w tym samym polu przedmiotu, gdzie moduł ładujący użyje odpowiedniego modułu obsługi, aby dodać te wartości.
Poniższy kod ilustruje, jak pozycje są zapełniane przy użyciu modułów ładujących -
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()
Jak pokazano powyżej, istnieją dwie różne ścieżki XPath, z których title pole jest wyodrębniane za pomocą add_xpath() metoda -
1. //div[@class = "product_title"]
2. //div[@class = "product_name"]
Następnie podobne żądanie jest używane do descpole. Dane o rozmiarze są wyodrębniane za pomocąadd_css() metoda i last_updated jest wypełniana wartością „wczoraj” za pomocą add_value() metoda.
Po zebraniu wszystkich danych zadzwoń ItemLoader.load_item() metoda, która zwraca elementy wypełnione danymi wyodrębnionymi za pomocą add_xpath(), add_css() i add_value() metody.
Procesory wejściowe i wyjściowe
Każde pole modułu ładującego elementy zawiera jeden procesor wejściowy i jeden procesor wyjściowy.
Po wyodrębnieniu danych procesor wejściowy przetwarza je, a jego wynik jest przechowywany w ItemLoader.
Następnie, po zebraniu danych, wywołaj metodę ItemLoader.load_item (), aby pobrać wypełniony obiekt Item.
Na koniec możesz przypisać wynik procesora wyjściowego do pozycji.
Poniższy kod ilustruje sposób wywoływania procesorów wejściowych i wyjściowych dla określonego pola -
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]
Line 1 - Dane tytułu są pobierane z xpath1 i przesyłane przez procesor wejściowy, a ich wynik jest gromadzony i zapisywany w ItemLoader.
Line 2 - Podobnie, tytuł jest wyodrębniany z xpath2 i przepuszczany przez ten sam procesor wejściowy, a jego wynik jest dodawany do danych zebranych dla [1].
Line 3 - Tytuł jest pobierany z selektora css i przepuszczany przez ten sam procesor wejściowy, a wynik jest dodawany do danych zebranych dla [1] i [2].
Line 4 - Następnie przypisywana jest wartość „demo” i przepuszczana przez procesory wejściowe.
Line 5 - Na koniec dane są zbierane wewnętrznie ze wszystkich pól i przekazywane do procesora wyjściowego, a ostateczna wartość jest przypisywana do elementu.
Deklarowanie procesorów wejściowych i wyjściowych
Procesory wejściowe i wyjściowe są zadeklarowane w definicji ItemLoader. Oprócz tego można je również określić w plikuItem Field metadane.
Na przykład -
import scrapy
from scrapy.loader.processors import Join, MapCompose, TakeFirst
from w3lib.html 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()
Wyświetla dane wyjściowe jako -
{'title': u'Hello world', 'size': u'100 kg'}
Kontekst modułu ładującego elementy
Kontekst modułu ładującego elementy jest zapisem arbitralnych wartości kluczowych współdzielonych między procesorami wejściowymi i wyjściowymi.
Na przykład załóżmy, że masz funkcję 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
Otrzymując argumenty loader_context, informuje program ładujący elementy, że może odebrać kontekst modułu ładującego elementy. Istnieje kilka sposobów zmiany wartości kontekstu modułu ładującego elementy -
Modyfikuj bieżący kontekst aktywnego modułu ładowania elementów -
loader = ItemLoader (product)
loader.context ["unit"] = "mm"
Podczas tworzenia instancji modułu ładującego przedmioty -
loader = ItemLoader(product, unit = "mm")
W przypadku deklaracji modułu ładującego elementy dla procesorów wejścia / wyjścia, które tworzą instancję z kontekstem modułu ładującego elementy -
class ProductLoader(ItemLoader):
length_out = MapCompose(parse_length, unit = "mm")
Obiekty ItemLoader
Jest to obiekt, który zwraca nowy program ładujący elementy, aby zapełnić dany element. Ma następującą klasę -
class scrapy.loader.ItemLoader([item, selector, response, ]**kwargs)
Poniższa tabela przedstawia parametry obiektów ItemLoader -
Sr.No | Parametr i opis |
---|---|
1 | item Jest to pozycja do zapełnienia przez wywołanie add_xpath (), add_css () lub add_value (). |
2 | selector Służy do pobierania danych ze stron internetowych. |
3 | response Służy do konstruowania selektora przy użyciu default_selector_class. |
Poniższa tabela przedstawia metody obiektów ItemLoader -
Sr.No | Metoda i opis | Przykład |
---|---|---|
1 | get_value(value, *processors, **kwargs) Wartość jest przetwarzana przez metodę get_value () przez podany procesor i argumenty słów kluczowych. |
|
2 | add_value(field_name, value, *processors, **kwargs) Przetwarza wartość i dodaje ją do pola, w którym jest po raz pierwszy przekazywana przez get_value, podając procesory i argumenty słów kluczowych przed przejściem przez procesor wejściowy pola. |
|
3 | replace_value(field_name, value, *processors, **kwargs) Zastępuje zebrane dane nową wartością. |
|
4 | get_xpath(xpath, *processors, **kwargs) Służy do wyodrębniania ciągów znaków Unicode przez podanie procesorów i argumentów słów kluczowych poprzez odebranie XPath . |
|
5 | add_xpath(field_name, xpath, *processors, **kwargs) Otrzymuje XPath do pola, które wyodrębnia ciągi znaków Unicode. |
|
6 | replace_xpath(field_name, xpath, *processors, **kwargs) Zastępuje zebrane dane za pomocą XPath z witryn. |
|
7 | get_css(css, *processors, **kwargs) Otrzymuje selektor CSS używany do wyodrębnienia ciągów znaków Unicode. |
|
8 | add_css(field_name, css, *processors, **kwargs) Jest podobna do metody add_value () z tą różnicą, że dodaje selektor CSS do pola. |
|
9 | replace_css(field_name, css, *processors, **kwargs) Zastępuje wyodrębnione dane za pomocą selektora CSS. |
|
10 | load_item() Po zebraniu danych ta metoda wypełnia pozycję zebranymi danymi i zwraca je. |
|
11 | nested_xpath(xpath) Służy do tworzenia zagnieżdżonych programów ładujących z selektorem XPath. |
|
12 | nested_css(css) Służy do tworzenia zagnieżdżonych programów ładujących z selektorem CSS. |
|
Poniższa tabela przedstawia atrybuty obiektów ItemLoader -
Sr.No | Atrybut i opis |
---|---|
1 | item Jest to obiekt, na którym moduł ładujący przedmioty przeprowadza analizę. |
2 | context Jest to bieżący kontekst programu ładującego elementy, który jest aktywny. |
3 | default_item_class Służy do reprezentowania elementów, jeśli nie jest podany w konstruktorze. |
4 | default_input_processor Pola, które nie określają procesora wejściowego, są jedynymi, dla których używane są default_input_processors. |
5 | default_output_processor Pola, które nie określają procesora wyjściowego, są jedynymi, dla których używane są default_output_processors. |
6 | default_selector_class Jest to klasa używana do konstruowania selektora, jeśli nie jest podana w konstruktorze. |
7 | selector Jest to obiekt, którego można użyć do wyodrębnienia danych z witryn. |
Ładowarki zagnieżdżone
Służy do tworzenia zagnieżdżonych programów ładujących podczas analizowania wartości z podsekcji dokumentu. Jeśli nie tworzysz zagnieżdżonych programów ładujących, musisz określić pełną XPath lub CSS dla każdej wartości, którą chcesz wyodrębnić.
Na przykład załóżmy, że dane są wyodrębniane ze strony nagłówkowej -
<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>
Następnie możesz utworzyć zagnieżdżony moduł ładujący z selektorem nagłówka, dodając powiązane wartości do nagłówka -
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()
Ponowne używanie i rozszerzanie programów ładujących przedmioty
Moduły ładujące przedmioty zostały zaprojektowane tak, aby odciążyć konserwację, co staje się podstawowym problemem, gdy do projektu przybywa więcej pająków.
Załóżmy na przykład, że witryna ma nazwę produktu zawartą w trzech myślnikach (np. --DVD ---). Możesz usunąć te myślniki, ponownie używając domyślnego modułu ładowania pozycji produktu, jeśli nie chcesz go w nazwach produktów końcowych, jak pokazano w poniższym kodzie -
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)
Dostępne procesory wbudowane
Poniżej przedstawiono niektóre z powszechnie używanych wbudowanych procesorów -
class scrapy.loader.processors.Identity
Zwraca oryginalną wartość bez jej zmiany. Na przykład -
>>> from scrapy.loader.processors import Identity
>>> proc = Identity()
>>> proc(['a', 'b', 'c'])
['a', 'b', 'c']
class scrapy.loader.processors.TakeFirst
Zwraca pierwszą wartość niezerową / niepustą z listy otrzymanych wartości. Na przykład -
>>> from scrapy.loader.processors import TakeFirst
>>> proc = TakeFirst()
>>> proc(['', 'a', 'b', 'c'])
'a'
class scrapy.loader.processors.Join (separator = u '')
Zwraca wartość dołączoną do separatora. Domyślnym separatorem jest u '' i jest odpowiednikiem funkcjiu' '.join. Na przykład -
>>> 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)
Jest definiowany przez procesor, w którym każda wartość wejściowa jest przekazywana do pierwszej funkcji, a wynik tej funkcji jest przekazywany do drugiej funkcji i tak dalej, aż funkcja ast zwróci wartość końcową jako wyjście.
Na przykład -
>>> 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)
Jest to procesor, w którym wartość wejściowa jest iterowana, a pierwsza funkcja jest stosowana do każdego elementu. Następnie wynik tych wywołań funkcji jest konkatenowany w celu zbudowania nowej iterowalnej, która jest następnie stosowana do drugiej funkcji i tak dalej, aż do ostatniej funkcji.
Na przykład -
>>> 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']
class scrapy.loader.processors.SelectJmes (json_path)
Ta klasa odpytuje wartość przy użyciu podanej ścieżki json i zwraca dane wyjściowe.
Na przykład -
>>> from scrapy.loader.processors import SelectJmes, Compose, MapCompose
>>> proc = SelectJmes("hello")
>>> proc({'hello': 'scrapy'})
'scrapy'
>>> proc({'hello': {'scrapy': 'world'}})
{'scrapy': 'world'}
Poniżej znajduje się kod, który wysyła zapytanie o wartość, importując 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']