Scrapy - Carregadores de Item

Descrição

Os carregadores de itens fornecem uma maneira conveniente de preencher os itens que são retirados dos sites.

Declaração de carregadores de itens

A declaração dos carregadores de itens é como itens.

Por exemplo -

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

No código acima, você pode ver que os processadores de entrada são declarados usando _in sufixo e processadores de saída são declarados usando _out sufixo.

o ItemLoader.default_input_processor e ItemLoader.default_output_processor atributos são usados ​​para declarar processadores de entrada / saída padrão.

Usando carregadores de itens para preencher itens

Para usar o carregador de itens, primeiro instancie com o objeto do tipo dict ou sem um onde o item use a classe de item especificada em ItemLoader.default_item_class atributo.

  • Você pode usar seletores para coletar valores no carregador de itens.

  • Você pode adicionar mais valores no mesmo campo de item, onde o Carregador de Itens usará um manipulador apropriado para adicionar esses valores.

O código a seguir demonstra como os itens são preenchidos usando carregadores de itens -

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

Conforme mostrado acima, existem dois XPaths diferentes dos quais o title campo é extraído usando add_xpath() método -

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

Depois disso, uma solicitação semelhante é usada para desccampo. Os dados de tamanho são extraídos usandoadd_css() método e last_updated é preenchido com um valor "ontem" usando add_value() método.

Assim que todos os dados forem coletados, ligue ItemLoader.load_item() método que retorna os itens preenchidos com dados extraídos usando add_xpath(), add_css() e add_value() métodos.

Processadores de entrada e saída

Cada campo de um carregador de itens contém um processador de entrada e um processador de saída.

  • Quando os dados são extraídos, o processador de entrada os processa e seu resultado é armazenado no ItemLoader.

  • Em seguida, após coletar os dados, chame o método ItemLoader.load_item () para obter o objeto Item preenchido.

  • Finalmente, você pode atribuir o resultado do processador de saída ao item.

O código a seguir demonstra como chamar processadores de entrada e saída para um campo específico -

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 - Os dados do título são extraídos de xpath1 e passados ​​pelo processador de entrada e seu resultado é coletado e armazenado no ItemLoader.

Line 2 - Da mesma forma, o título é extraído de xpath2 e passado pelo mesmo processador de entrada e seu resultado é adicionado aos dados coletados para [1].

Line 3 - O título é extraído do seletor css e passado pelo mesmo processador de entrada e o resultado é adicionado aos dados coletados para [1] e [2].

Line 4 - Em seguida, o valor "demo" é atribuído e passado pelos processadores de entrada.

Line 5 - Por fim, os dados são coletados internamente de todos os campos e passados ​​para o processador de saída e o valor final é atribuído ao Item.

Declaração de processadores de entrada e saída

Os processadores de entrada e saída são declarados na definição ItemLoader. Além disso, eles também podem ser especificados noItem Field metadados.

Por exemplo -

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

Ele exibe uma saída como -

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

Contexto do carregador de itens

O Item Loader Context é um dicionário de valores-chave arbitrários compartilhados entre os processadores de entrada e saída.

Por exemplo, suponha que você tenha uma função 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

Ao receber argumentos loader_context, ele informa ao carregador de itens que pode receber o contexto do carregador de itens. Existem várias maneiras de alterar o valor do contexto do carregador de itens -

  • Modificar o contexto atual do carregador de item ativo -

loader = ItemLoader (product)
loader.context ["unit"] = "mm"
  • Na instanciação do carregador de itens -

loader = ItemLoader(product, unit = "mm")
  • Na declaração do carregador de itens para processadores de entrada / saída que instanciam com o contexto do carregador de itens -

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

Objetos ItemLoader

É um objeto que retorna um novo carregador de item para preencher o item fornecido. Tem a seguinte classe -

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

A tabela a seguir mostra os parâmetros dos objetos ItemLoader -

Sr. Não Parâmetro e Descrição
1

item

É o item a preencher chamando add_xpath (), add_css () ou add_value ().

2

selector

Ele é usado para extrair dados de sites.

3

response

É usado para construir o seletor usando default_selector_class.

A tabela a seguir mostra os métodos de objetos ItemLoader -

Sr. Não Método e Descrição Exemplo
1

get_value(value, *processors, **kwargs)

Por um determinado processador e argumentos de palavra-chave, o valor é processado pelo método 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)

Ele processa o valor e adiciona ao campo onde é passado pela primeira vez por get_value, fornecendo argumentos de processadores e palavras-chave antes de passar pelo processador de entrada de 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)

Ele substitui os dados coletados por um novo valor.

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)

Ele é usado para extrair cadeias de caracteres Unicode fornecendo processadores e argumentos de palavra-chave ao receber 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)

Ele recebe XPath para o campo que extrai strings 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)

Ele substitui os dados coletados usando XPath de sites.

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

Ele recebe o seletor CSS usado para extrair as strings 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)

É semelhante ao método add_value () com uma diferença que adiciona o seletor CSS ao 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)

Ele substitui os dados extraídos usando o seletor CSS.

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

load_item()

Quando os dados são coletados, esse método preenche o item com os dados coletados e os retorna.

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)

É usado para criar carregadores aninhados com um seletor 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)

É usado para criar carregadores aninhados com um seletor CSS.

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

A tabela a seguir mostra os atributos dos objetos ItemLoader -

Sr. Não Atributo e descrição
1

item

É um objeto no qual o carregador de itens executa a análise.

2

context

É o contexto atual do carregador de itens que está ativo.

3

default_item_class

É usado para representar os itens, se não for fornecido no construtor.

4

default_input_processor

Os campos que não especificam o processador de entrada são os únicos para os quais default_input_processors são usados.

5

default_output_processor

Os campos que não especificam o processador de saída são os únicos para os quais default_output_processors são usados.

6

default_selector_class

É uma classe usada para construir o seletor, se não for fornecido no construtor.

7

selector

É um objeto que pode ser usado para extrair os dados dos sites.

Carregadores aninhados

Ele é usado para criar carregadores aninhados enquanto analisa os valores da subseção de um documento. Se você não criar carregadores aninhados, precisará especificar XPath ou CSS completo para cada valor que deseja extrair.

Por exemplo, suponha que os dados estejam sendo extraídos de uma página de cabeçalho -

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

Em seguida, você pode criar um carregador aninhado com seletor de cabeçalho, adicionando valores relacionados ao cabeçalho -

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

Reutilizar e ampliar carregadores de itens

Os carregadores de itens são projetados para aliviar a manutenção que se torna um problema fundamental quando o seu projeto adquire mais spiders.

Por exemplo, suponha que um site tenha o nome do produto entre três travessões (por exemplo, --DVD ---). Você pode remover esses travessões reutilizando o carregador de itens de produto padrão, se não quiser nos nomes dos produtos finais, conforme mostrado no código a seguir -

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)

Processadores integrados disponíveis

A seguir estão alguns dos processadores integrados comumente usados ​​-

classe scrapy.loader.processors.Identity

Ele retorna o valor original sem alterá-lo. Por exemplo -

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

classe scrapy.loader.processors.TakeFirst

Retorna o primeiro valor não nulo / não vazio da lista de valores recebidos. Por exemplo -

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

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

Ele retorna o valor anexado ao separador. O separador padrão é u '' e é equivalente à funçãou' '.join. Por exemplo -

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

classe scrapy.loader.processors.Compose (* funções, ** default_loader_context)

É definido por um processador onde cada um de seus valores de entrada é passado para a primeira função, e o resultado dessa função é passado para a segunda função e assim por diante, até que a função ast retorne o valor final como saída.

Por exemplo -

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

classe scrapy.loader.processors.MapCompose (* funções, ** default_loader_context)

É um processador onde o valor de entrada é iterado e a primeira função é aplicada a cada elemento. Em seguida, o resultado dessas chamadas de função são concatenados para construir um novo iterável que é então aplicado à segunda função e assim por diante, até a última função.

Por exemplo -

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

classe scrapy.loader.processors.SelectJmes (json_path)

Esta classe consulta o valor usando o caminho json fornecido e retorna a saída.

Por exemplo -

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

A seguir está o código, que consulta o valor 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']