Scrapy - Caricatori di oggetti

Descrizione

I caricatori di articoli forniscono un modo conveniente per riempire gli articoli che vengono raschiati dai siti web.

Dichiarazione di caricatori di articoli

La dichiarazione di Item Loaders è come Articoli.

Ad esempio:

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

Nel codice sopra, puoi vedere che i processori di input sono dichiarati usando _in suffisso e processori di output vengono dichiarati utilizzando _out suffisso.

Il ItemLoader.default_input_processor e ItemLoader.default_output_processor gli attributi vengono utilizzati per dichiarare i processori di input / output predefiniti.

Utilizzo dei caricatori di articoli per popolare gli articoli

Per utilizzare Item Loader, crea prima un'istanza con un oggetto simile a un dict o senza uno in cui l'elemento utilizza la classe Item specificata in ItemLoader.default_item_class attributo.

  • È possibile utilizzare i selettori per raccogliere i valori nel caricatore articolo.

  • È possibile aggiungere più valori nello stesso campo articolo, dove Item Loader utilizzerà un gestore appropriato per aggiungere questi valori.

Il codice seguente mostra come gli elementi vengono popolati utilizzando Item Loaders -

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

Come mostrato sopra, ci sono due diversi XPath da cui il file title campo viene estratto utilizzando add_xpath() metodo -

1. //div[@class = "product_title"] 
2. //div[@class = "product_name"]

Successivamente, viene utilizzata una richiesta simile per desccampo. I dati sulle dimensioni vengono estratti utilizzandoadd_css() metodo e last_updated viene riempito con un valore "ieri" utilizzando add_value() metodo.

Una volta raccolti tutti i dati, chiama ItemLoader.load_item() metodo che restituisce gli elementi riempiti con i dati estratti utilizzando add_xpath(), add_css() e add_value() metodi.

Processori di input e output

Ogni campo di un Item Loader contiene un processore di input e un processore di output.

  • Quando i dati vengono estratti, il processore di input li elabora e il suo risultato viene memorizzato in ItemLoader.

  • Successivamente, dopo aver raccolto i dati, chiama il metodo ItemLoader.load_item () per ottenere l'oggetto Item popolato.

  • Infine, puoi assegnare il risultato del processore di output all'elemento.

Il codice seguente mostra come chiamare i processori di input e output per un campo specifico:

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 - I dati del titolo vengono estratti da xpath1 e passati attraverso il processore di input e il suo risultato viene raccolto e archiviato in ItemLoader.

Line 2 - Allo stesso modo, il titolo viene estratto da xpath2 e passato attraverso lo stesso processore di input e il suo risultato viene aggiunto ai dati raccolti per [1].

Line 3 - Il titolo viene estratto dal selettore css e passato attraverso lo stesso processore di input e il risultato viene aggiunto ai dati raccolti per [1] e [2].

Line 4 - Successivamente, il valore "demo" viene assegnato e passato attraverso i processori di input.

Line 5 - Infine, i dati vengono raccolti internamente da tutti i campi e passati al processore di output e il valore finale viene assegnato all'Articolo.

Dichiarazione di processori di input e output

I processori di input e output sono dichiarati nella definizione ItemLoader. Oltre a questo, possono anche essere specificati nel fileItem Field metadati.

Ad esempio:

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

Visualizza un output come -

{'title': u'Hello world', 'size': u'100 kg'}

Contesto caricatore articolo

Item Loader Context è un dettato di valori chiave arbitrari condivisi tra processori di input e output.

Ad esempio, supponi di avere una funzione 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

Ricevendo argomenti loader_context, comunica a Item Loader che può ricevere il contesto Item Loader. Esistono diversi modi per modificare il valore del contesto Item Loader:

  • Modifica il contesto del caricatore articolo attivo corrente -

loader = ItemLoader (product)
loader.context ["unit"] = "mm"
  • Sulla creazione di istanze di Item Loader -

loader = ItemLoader(product, unit = "mm")
  • Sulla dichiarazione Item Loader per processori di input / output che crea un'istanza con il contesto Item Loader -

class ProductLoader(ItemLoader):
   length_out = MapCompose(parse_length, unit = "mm")

Oggetti ItemLoader

È un oggetto che restituisce un nuovo caricatore di elementi per popolare l'elemento specificato. Ha la seguente classe:

class scrapy.loader.ItemLoader([item, selector, response, ]**kwargs)

La tabella seguente mostra i parametri degli oggetti ItemLoader:

Suor n Parametro e descrizione
1

item

È l'elemento da popolare chiamando add_xpath (), add_css () o add_value ().

2

selector

Viene utilizzato per estrarre dati dai siti Web.

3

response

Viene utilizzato per costruire selector utilizzando default_selector_class.

La tabella seguente mostra i metodi degli oggetti ItemLoader:

Suor n Metodo e descrizione Esempio
1

get_value(value, *processors, **kwargs)

Da un determinato processore e argomenti di parole chiave, il valore viene elaborato dal metodo 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)

Elabora il valore e aggiunge al campo in cui è passato per la prima volta attraverso get_value fornendo processori e argomenti di parole chiave prima di passare attraverso il processore di input del campo.

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)

Sostituisce i dati raccolti con un nuovo valore.

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)

Viene utilizzato per estrarre stringhe Unicode fornendo processori e argomenti di parole chiave ricevendo XPath .

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

Riceve XPath nel campo che estrae le stringhe Unicode.

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

Sostituisce i dati raccolti utilizzando XPath dai siti.

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

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

get_css(css, *processors, **kwargs)

Riceve il selettore CSS utilizzato per estrarre le stringhe Unicode.

loader.get_css("div.item-name")
loader.get_css("div#length", TakeFirst(), 
re = "the length is (.*)")
8

add_css(field_name, css, *processors, **kwargs)

È simile al metodo add_value () con una differenza che aggiunge il selettore CSS al campo.

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)

Sostituisce i dati estratti utilizzando il selettore CSS.

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

load_item()

Quando i dati vengono raccolti, questo metodo riempie l'articolo con i dati raccolti e lo restituisce.

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)

Viene utilizzato per creare caricatori nidificati con un selettore 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)

Viene utilizzato per creare caricatori nidificati con un selettore CSS.

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

La tabella seguente mostra gli attributi degli oggetti ItemLoader:

Suor n Attributo e descrizione
1

item

È un oggetto su cui Item Loader esegue l'analisi.

2

context

È il contesto corrente di Item Loader che è attivo.

3

default_item_class

Viene utilizzato per rappresentare gli elementi, se non specificato nel costruttore.

4

default_input_processor

I campi che non specificano il processore di input sono gli unici per i quali vengono utilizzati default_input_processors.

5

default_output_processor

I campi che non specificano il processore di output sono gli unici per i quali vengono utilizzati default_output_processors.

6

default_selector_class

È una classe usata per costruire il selettore, se non è data nel costruttore.

7

selector

È un oggetto che può essere utilizzato per estrarre i dati dai siti.

Caricatori annidati

Viene utilizzato per creare caricatori annidati durante l'analisi dei valori dalla sottosezione di un documento. Se non crei caricatori nidificati, devi specificare XPath o CSS completi per ogni valore che desideri estrarre.

Ad esempio, supponiamo che i dati vengano estratti da una pagina di intestazione:

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

Successivamente, puoi creare un caricatore nidificato con il selettore di intestazione aggiungendo valori correlati all'intestazione -

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

Riutilizzo ed estensione dei caricatori di articoli

I caricatori di oggetti sono progettati per alleviare la manutenzione che diventa un problema fondamentale quando il tuo progetto acquisisce più ragni.

Ad esempio, supponiamo che un sito abbia il nome del prodotto racchiuso tra tre trattini (ad esempio --DVD ---). È possibile rimuovere quei trattini riutilizzando il caricatore di articoli prodotto predefinito, se non lo si desidera nei nomi dei prodotti finali come mostrato nel codice seguente:

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)

Processori integrati disponibili

Di seguito sono riportati alcuni dei processori integrati comunemente usati:

class scrapy.loader.processors.Identity

Restituisce il valore originale senza alterarlo. Ad esempio:

>>> from scrapy.loader.processors import Identity
>>> proc = Identity()
>>> proc(['a', 'b', 'c'])
['a', 'b', 'c']

class scrapy.loader.processors.TakeFirst

Restituisce il primo valore non nullo / non vuoto dall'elenco dei valori ricevuti. Ad esempio:

>>> from scrapy.loader.processors import TakeFirst
>>> proc = TakeFirst()
>>> proc(['', 'a', 'b', 'c'])
'a'

class scrapy.loader.processors.Join (separator = u '')

Restituisce il valore allegato al separatore. Il separatore predefinito è u '' ed è equivalente alla funzioneu' '.join. Ad esempio:

>>> 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 (* funzioni, ** default_loader_context)

È definito da un processore in cui ciascuno dei suoi valori di input viene passato alla prima funzione, e il risultato di quella funzione viene passato alla seconda funzione e così via, finché la funzione ast non restituisce il valore finale come output.

Ad esempio:

>>> from scrapy.loader.processors import Compose
>>> proc = Compose(lambda v: v[0], str.upper)
>>> proc(['python', 'scrapy'])
'PYTHON'

class scrapy.loader.processors.MapCompose (* funzioni, ** default_loader_context)

È un processore in cui il valore di input viene iterato e la prima funzione viene applicata a ciascun elemento. Successivamente, il risultato di queste chiamate di funzione viene concatenato per creare un nuovo iterabile che viene quindi applicato alla seconda funzione e così via, fino all'ultima funzione.

Ad esempio:

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

Questa classe interroga il valore utilizzando il percorso json fornito e restituisce l'output.

Ad esempio:

>>> from scrapy.loader.processors import SelectJmes, Compose, MapCompose
>>> proc = SelectJmes("hello")
>>> proc({'hello': 'scrapy'})
'scrapy'
>>> proc({'hello': {'scrapy': 'world'}})
{'scrapy': 'world'}

Di seguito è riportato il codice, che interroga il valore importando 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']