Scrapy教程

Scrapy 字段加载

说明

项目加载器提供了一种方便的方式来填充从网站上抓取的项目。

声明项目加载器

Item Loaders 的声明就像 Items。
例如-
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_processorItemLoader.default_output_processor 属性用于声明默认输入/输出处理器。

使用项目加载器来填充项目

要使用 Item Loader,首先使用类似 dict 的对象进行实例化,或者在项目使用 ItemLoader 中指定的 Item 类的情况下不进行实例化。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()
如上所示,有两个不同的 XPath 使用 add_xpath() 方法从中提取 title 字段-
1. //div[@class = "product_title"] 
2. //div[@class = "product_name"]
此后,对 desc 字段使用类似的请求。使用 add_css() 方法提取尺寸数据,使用 add_value() 方法将 last_updated 填充为"昨天"值。
收集完所有数据后,调用 ItemLoader.load_item() 方法,该方法返回填充了使用 add_xpath()add_css() 提取的数据的项目add_value() 方法。

输入和输出处理器

Item Loader 的每个字段包含一个输入处理器和一个输出处理器。
提取数据后,输入处理器会对其进行处理,并将其结果存储在 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 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()
它将输出显示为-
{'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")
使用 Item Loader 上下文实例化的输入/输出处理器的 On Item Loader 声明-
class ProductLoader(ItemLoader):
   length_out = MapCompose(parse_length, unit = "mm")

ItemLoader 对象

它是一个对象,它返回一个新的项目加载器来填充给定的项目。它有以下类-
class scrapy.loader.ItemLoader([item, selector, response, ]**kwargs)
下表显示了 ItemLoader 对象的参数-
参数和说明
item
它是通过调用 add_xpath()、add_css() 或 add_value() 来填充的项目。
selector
用于从网站中提取数据。
response
用于使用default_selector_class构造选择器。
下表显示了 ItemLoader 对象的方法-
方法和说明 示例
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`
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')
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')
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 (.*)")
add_xpath(field_name, xpath, *processors, **kwargs)
它接收 XPath到提取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 (.*)')
replace_xpath(field_name, xpath, *processors, **kwargs)
它使用 XPath 从站点替换收集的数据。
# 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 (.*)')
get_css(css, *processors, **kwargs)
它接收用于提取unicode字符串的CSS选择器。
loader.get_css("div.item-name")
loader.get_css("div#length", TakeFirst(), 
re = "the length is (.*)")
add_css(field_name, css, *processors, **kwargs)
它与 add_value() 方法类似,但有一个区别是它添加了 CSS 选择器领域。
loader.add_css('name', 'div.item-name')
loader.add_css('length', 'div#length', 
re = 'the length is (.*)')
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 (.*)')
load_item()
当收集到数据时,此方法用收集到的数据填充项目并返回。
def parse(self, response):
l = ItemLoader(item = Product(), 
response = response)
l.add_xpath('title', '//
div[@class = "product_title"]')
loader.load_item()
nested_xpath(xpath)
它用于创建带有 XPath 选择器的嵌套加载器。
loader = ItemLoader(item = Item())
loader.add_xpath('social', '
a[@class = "social"]/@href')
loader.add_xpath('email', '
a[@class = "email"]/@href')
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 对象的属性-
属性和描述
item
Item Loader 解析的对象。
context
它是当前处于活动状态的项目加载器的上下文。
default_item_class
如果没有在构造函数中给出,则用于表示项目。
default_input_processor
未指定输入处理器的字段是唯一使用 default_input_processor 的字段。
default_output_processor
未指定输出处理器的字段是唯一使用 default_output_processor 的字段。
default_selector_class
如果在构造器中没有给出,则是用来构造选择器的类。
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:someone@example.com">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()

重用和扩展项目加载器

项目加载器旨在减轻维护,当您的项目获得更多爬虫时,维护成为一个基本问题。
例如,假设一个站点的产品名称包含在三个破折号中(例如--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

它返回接收值列表中第一个非空/非空的值。例如-
>>> 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)

它由处理器定义,其中每个输入值都传递给第一个函数,该函数的结果传递给第二个函数,依此类推,直到 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)

它是一个处理器,其中迭代输入值并将第一个函数应用于每个元素。接下来,将这些函数调用的结果连接起来以构建新的可迭代对象,然后将其应用于第二个函数,依此类推,直到最后一个函数。
例如-
>>> 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)

该类使用提供的 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']
昵称: 邮箱:
Copyright © 2022 立地货 All Rights Reserved.
备案号:京ICP备14037608号-4