Scrapy Item Loaders Scrapy项目 Scrapy shell 描述 项目装载机提供了一种方便的方式来填充从网站上刮取的项目。 声明项目加载器 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_processor 和 ItemLoader.default_output_processor 属性用于声明默认输入/输出处理器。 使用项目加载器来填充项目 要使用Item Loader,首先使用类似字典的对象进行实例化,或者不要使用 ItemLoader.default_item_class 属性中指定的Item类。 您可以使用选择器将值收集到Item Loader中。 您可以在同一个项目字段中添加更多值,其中Item Loader将使用适当的处理程序来添加这些值。 以下代码演示了如何使用项目加载器填充项目 - 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() 方法从中提取 标题 字段- ** 1. //div[@class = "product_title"] 2. //div[@class = "product_name"] 此后,类似的请求用于 desc 字段。大小数据是使用提取 add_css() 方法和 LAST_UPDATED 填充有值“昨天”使用 add_value() 方法。 一旦收集完所有数据,调用 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定义中声明。除此之外,还可以在 项目字段 元数据中指定它们。 例如 - 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'} 项目加载器上下文 Item Loader Context是输入和输出处理器之间共享的任意键值的字典。 例如,假设你有一个函数 _parselength - 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上下文。有几种方法可以更改Item Loader上下文的值 - 修改当前活动的Item Loader上下文 - loader = ItemLoader (product) loader.context ["unit"] = "mm" Item Loader实例化 - loader = ItemLoader(product, unit = "mm") 在Item Loader上下文中实例化的输入/输出处理器的Item Loader声明 - class ProductLoader(ItemLoader): length_out = MapCompose(parse_length, unit = "mm") ItemLoader对象 这是一个对象,它返回一个新的项目加载器来填充给定的项目。它有以下班级 - class scrapy.loader.ItemLoader([item, selector, response, ] ** kwargs) 下表显示了ItemLoader对象的参数 - Sr.No 参数和说明 1 item 它是通过调用add_xpath(),add_css()或add_value()来填充的项目。 2 selector 它用于从网站提取数据。 3 response 它用于使用default_selector_class构造选择器。 下表显示了ItemLoader对象的方法 - Sr.No 方法和描述 实例 1 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` 2 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') 3 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') 4 get_xpath(xpath, *processors, ** kwargs) 它用于通过接收 _XPath_ 提供处理器和关键字参数来提取unicode字符串。 # HTML code: DVD loader.get_xpath("//div[@class = 'item-name']") # HTML code: the length is 45cm loader.get_xpath("//div[@id = 'length']", TakeFirst(), re = "the length is (.*)") 5 add_xpath(field_name,xpath,* processors,** kwargs) 它接收到提取unicode字符串的字段的 _XPath_ 。 # HTML code: DVD loader.add_xpath('name', '//div[@class = "item-name"]') # HTML code: the length is 45cm loader.add_xpath('length', '//div[@id = "length"]', re = 'the length is (.*)') 6 replace_xpath(field_name,xpath,* processors,** kwargs) 它使用来自站点的 _XPath_ 替换收集的数据。 # HTML code: DVD loader.replace_xpath('name', '//div[@class = "item-name"]') # HTML code: the length is 45cm loader.replace_xpath('length', '//div[@id = "length"]', re = 'the length is (.*)') 7 get_css(css, *processors, **kwargs) 它接收用于提取unicode字符串的CSS选择器。 loader.get_css("div.item-name") loader.get_css("div#length", TakeFirst(), re = "the length is (.*)") 8 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 (.*)') 9 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 (.*)') 10 load_item() 收集数据时,此方法使用收集的数据填充项目并将其返回。 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) 它用于使用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) 它用于创建具有CSS选择器的嵌套加载器。 loader = ItemLoader(item = Item()) loader.add_css('social', 'a[@class = "social"]/@href') loader.add_css('email', 'a[@class = "email"]/@href') 下表显示了ItemLoader对象的属性 - 序号 属性和描述 1 item 它是Item Loader执行解析的对象。 2 context Item Loader的当前上下文是活动的。 3 default_item_class 它用于表示项目,如果没有在构造函数中给出。 4 default_input_processor 没有指定输入处理器的字段是唯一使用default_input_processors的字段。 五 default_output_processor 未指定输出处理器的字段是唯一使用default_output_processors的字段。 6 default_selector_class 它是一个用于构造选择器的类,如果它没有在构造函数中给出的话。 7 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 ---)。如果您不想在最终产品名称中使用它,您可以通过重新使用默认Product Item Loader来删除这些破折号 - 如下面的代码所示 - 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' 类scrapy.loader.processors.Compose(*函数,** default_loader_context) 它由处理器定义,其中每个输入值都传递给第一个函数,并将该函数的结果传递给第二个函数,直到ast函数返回最终值作为输出。 例如 - >>> from scrapy.loader.processors import Compose >>> proc = Compose(lambda v: v[0], str.upper) >>> proc(['python', 'scrapy']) 'PYTHON' 类scrapy.loader.processors.MapCompose(*函数,** 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'] 类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'] Scrapy项目 Scrapy shell