Scrapy: cargadores de artículos
Descripción
Los cargadores de artículos proporcionan una forma conveniente de llenar los artículos que se extraen de los sitios web.
Declarar cargadores de artículos
La declaración de cargadores de artículos es como artículos.
Por ejemplo
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
En el código anterior, puede ver que los procesadores de entrada se declaran usando _in Los procesadores de sufijo y salida se declaran usando _out sufijo.
los ItemLoader.default_input_processor y ItemLoader.default_output_processor Los atributos se utilizan para declarar procesadores de entrada / salida predeterminados.
Uso de cargadores de elementos para completar elementos
Para usar el Cargador de artículos, primero cree una instancia con un objeto similar a dict o sin uno donde el artículo use la clase de artículo especificada en ItemLoader.default_item_class atributo.
Puede utilizar selectores para recopilar valores en el Cargador de artículos.
Puede agregar más valores en el mismo campo de artículo, donde Item Loader utilizará un controlador apropiado para agregar estos valores.
El siguiente código demuestra cómo se rellenan los elementos con los cargadores de elementos:
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()
Como se muestra arriba, hay dos XPaths diferentes de los cuales el title el campo se extrae usando add_xpath() método -
1. //div[@class = "product_title"]
2. //div[@class = "product_name"]
A partir de entonces, se utiliza una solicitud similar para desccampo. Los datos de tamaño se extraen usandoadd_css() método y last_updated se rellena con un valor "ayer" utilizando add_value() método.
Una vez recopilados todos los datos, llame ItemLoader.load_item() método que devuelve los elementos llenos de datos extraídos utilizando add_xpath(), add_css() y add_value() métodos.
Procesadores de entrada y salida
Cada campo de un cargador de artículos contiene un procesador de entrada y un procesador de salida.
Cuando se extraen los datos, el procesador de entrada los procesa y su resultado se almacena en ItemLoader.
A continuación, después de recopilar los datos, llame al método ItemLoader.load_item () para obtener el objeto Item poblado.
Finalmente, puede asignar el resultado del procesador de salida al artículo.
El siguiente código demuestra cómo llamar a procesadores de entrada y salida para un 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 - Los datos del título se extraen de xpath1 y se pasan a través del procesador de entrada y su resultado se recopila y almacena en ItemLoader.
Line 2 - De manera similar, el título se extrae de xpath2 y se pasa por el mismo procesador de entrada y su resultado se agrega a los datos recopilados para [1].
Line 3 - El título se extrae del selector css y se pasa por el mismo procesador de entrada y el resultado se agrega a los datos recopilados para [1] y [2].
Line 4 - A continuación, se asigna el valor "demo" y se pasa a través de los procesadores de entrada.
Line 5 - Finalmente, los datos se recopilan internamente de todos los campos y se pasan al procesador de salida y el valor final se asigna al artículo.
Declaración de procesadores de entrada y salida
Los procesadores de entrada y salida se declaran en la definición de ItemLoader. Aparte de esto, también se pueden especificar en elItem Field metadatos.
Por ejemplo
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()
Muestra una salida como:
{'title': u'Hello world', 'size': u'100 kg'}
Contexto del cargador de artículos
El contexto del cargador de elementos es un dictado de valores clave arbitrarios compartidos entre procesadores de entrada y salida.
Por ejemplo, suponga que tiene una función 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
Al recibir argumentos de loader_context, le dice al Cargador de artículos que puede recibir el contexto del Cargador de artículos. Hay varias formas de cambiar el valor del contexto del cargador de artículos:
Modificar el contexto actual del cargador de elementos activo -
loader = ItemLoader (product)
loader.context ["unit"] = "mm"
En la instanciación de Item Loader -
loader = ItemLoader(product, unit = "mm")
En la declaración de Item Loader para procesadores de entrada / salida que crea una instancia con el contexto de Item Loader -
class ProductLoader(ItemLoader):
length_out = MapCompose(parse_length, unit = "mm")
Objetos ItemLoader
Es un objeto que devuelve un nuevo cargador de elementos para completar el elemento dado. Tiene la siguiente clase:
class scrapy.loader.ItemLoader([item, selector, response, ]**kwargs)
La siguiente tabla muestra los parámetros de los objetos ItemLoader:
No Señor | Descripción de parámetros |
---|---|
1 | item Es el elemento que se debe completar llamando a add_xpath (), add_css () o add_value (). |
2 | selector Se utiliza para extraer datos de sitios web. |
3 | response Se usa para construir el selector usando default_selector_class. |
La siguiente tabla muestra los métodos de los objetos ItemLoader:
No Señor | Método y descripción | Ejemplo |
---|---|---|
1 | get_value(value, *processors, **kwargs) Por un procesador dado y argumentos de palabra clave, el valor es procesado por el método get_value (). |
|
2 | add_value(field_name, value, *processors, **kwargs) Procesa el valor y lo agrega al campo donde primero se pasa a través de get_value dando procesadores y argumentos de palabras clave antes de pasar por el procesador de entrada de campo. |
|
3 | replace_value(field_name, value, *processors, **kwargs) Reemplaza los datos recopilados por un nuevo valor. |
|
4 | get_xpath(xpath, *processors, **kwargs) Se utiliza para extraer cadenas Unicode dando procesadores y argumentos de palabras clave al recibir XPath . |
|
5 | add_xpath(field_name, xpath, *processors, **kwargs) Recibe XPath en el campo que extrae cadenas Unicode. |
|
6 | replace_xpath(field_name, xpath, *processors, **kwargs) Reemplaza los datos recopilados mediante XPath de los sitios. |
|
7 | get_css(css, *processors, **kwargs) Recibe el selector de CSS que se utiliza para extraer las cadenas unicode. |
|
8 | add_css(field_name, css, *processors, **kwargs) Es similar al método add_value () con la diferencia de que agrega un selector CSS al campo. |
|
9 | replace_css(field_name, css, *processors, **kwargs) Reemplaza los datos extraídos usando el selector CSS. |
|
10 | load_item() Cuando se recopilan los datos, este método llena el artículo con los datos recopilados y lo devuelve. |
|
11 | nested_xpath(xpath) Se utiliza para crear cargadores anidados con un selector XPath. |
|
12 | nested_css(css) Se utiliza para crear cargadores anidados con un selector de CSS. |
|
La siguiente tabla muestra los atributos de los objetos ItemLoader:
No Señor | Atributo y descripción |
---|---|
1 | item Es un objeto en el que Item Loader realiza un análisis. |
2 | context Es el contexto actual de Item Loader el que está activo. |
3 | default_item_class Se utiliza para representar los elementos, si no se da en el constructor. |
4 | default_input_processor Los campos que no especifican el procesador de entrada son los únicos para los que se utilizan default_input_processors. |
5 | default_output_processor Los campos que no especifican el procesador de salida son los únicos para los que se utilizan default_output_processors. |
6 | default_selector_class Es una clase que se usa para construir el selector, si no se da en el constructor. |
7 | selector Es un objeto que se puede utilizar para extraer los datos de los sitios. |
Cargadores anidados
Se utiliza para crear cargadores anidados mientras se analizan los valores de la subsección de un documento. Si no crea cargadores anidados, debe especificar XPath o CSS completos para cada valor que desee extraer.
Por ejemplo, suponga que los datos se extraen de una página de encabezado:
<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>
A continuación, puede crear un cargador anidado con selector de encabezado agregando valores relacionados al encabezado:
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()
Reutilización y ampliación de cargadores de artículos
Los cargadores de artículos están diseñados para aliviar el mantenimiento que se convierte en un problema fundamental cuando su proyecto adquiere más arañas.
Por ejemplo, suponga que un sitio tiene el nombre de su producto entre tres guiones (por ejemplo, --DVD ---). Puede eliminar esos guiones reutilizando el Cargador de artículos de producto predeterminado, si no lo desea en los nombres de productos finales como se muestra en el siguiente código:
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)
Procesadores integrados disponibles
A continuación se muestran algunos de los procesadores integrados de uso común:
clase scrapy.loader.processors.Identity
Devuelve el valor original sin alterarlo. Por ejemplo
>>> from scrapy.loader.processors import Identity
>>> proc = Identity()
>>> proc(['a', 'b', 'c'])
['a', 'b', 'c']
clase scrapy.loader.processors.TakeFirst
Devuelve el primer valor que no es nulo / no está vacío de la lista de valores recibidos. Por ejemplo
>>> from scrapy.loader.processors import TakeFirst
>>> proc = TakeFirst()
>>> proc(['', 'a', 'b', 'c'])
'a'
clase scrapy.loader.processors.Join (separador = u '')
Devuelve el valor adjunto al separador. El separador predeterminado es u '' y es equivalente a la funciónu' '.join. Por ejemplo
>>> 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'
clase scrapy.loader.processors.Compose (* funciones, ** default_loader_context)
Está definido por un procesador donde cada uno de sus valores de entrada se pasa a la primera función, y el resultado de esa función se pasa a la segunda función y así sucesivamente, hasta que la función ast devuelve el valor final como salida.
Por ejemplo
>>> from scrapy.loader.processors import Compose
>>> proc = Compose(lambda v: v[0], str.upper)
>>> proc(['python', 'scrapy'])
'PYTHON'
clase scrapy.loader.processors.MapCompose (* funciones, ** default_loader_context)
Es un procesador donde se itera el valor de entrada y se aplica la primera función a cada elemento. A continuación, el resultado de estas llamadas de función se concatenan para crear un nuevo iterable que luego se aplica a la segunda función y así sucesivamente, hasta la última función.
Por ejemplo
>>> 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']
clase scrapy.loader.processors.SelectJmes (json_path)
Esta clase consulta el valor utilizando la ruta json proporcionada y devuelve el resultado.
Por ejemplo
>>> from scrapy.loader.processors import SelectJmes, Compose, MapCompose
>>> proc = SelectJmes("hello")
>>> proc({'hello': 'scrapy'})
'scrapy'
>>> proc({'hello': {'scrapy': 'world'}})
{'scrapy': 'world'}
A continuación se muestra el código, que consulta el 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']