hey 这是scrapy的第二篇,将记录Item的处理
1. 一次parse,获取多个item
- 获取selector列表
- 遍历列表,最后返回
yield item
def parse(self, response):
base_xpath = response.css('div.app-tab li.first .list-in') # 获得遍历列表
for i in base_xpath:
if base_xpath:
item = TsyTtItem() # 初始化item
item['game_name'] = base_xpath.css('.list-right .g-name>a::text').extract_first()
item['game_href'] = base_xpath.css('a::attr(href)').extract_first()
item['download_people'] = None
item['game_company'] = None
item['game_point'] = base_xpath.xpath('div[@class="list-right"]//span[@class="red"]/span[@class="big"]/text()').extract_first()+'.'+base_xpath.xpath('div[@class="list-right"]//span[@class="red"]/span[@class="small"]/text()').extract_first()
item['game_tag'] = base_xpath.css('.list-right .g-desc::text').extract_first().strip().split(',')
item['game_from'] = 'dangle'
yield item
item 扩展 item装载器
ItemLoader
- 导入 ItemLoader
from scrapy.loader import ItemLoader
- 传入创建的Item类和HtmlResponsed对象
item = ItemLoader(item=PropertiesItem(), response=response)
parse(self, response)中的response 其实是HtmlResponse对象- 直接调用item的方法来往item对象中添加字段代赋值的方法(先保存在item中,最后需要返回item.load_item()用来释放字段及值)
item['game_href'] = base_xpath.css('a::attr(href)').extract()
item.add_xpath(self, field_name, xpath, *processors, **kw)
返回的为列表item.add_css(self, field_name, css, *processors, **kw)
返回的为列表add_value(self, field_name, value, *processors, **kw)
返回的为列表
- 参数解释:
field_name
对应item.py
中的 Item中初始化的字段 例如:title = scrapy.Field()
- 选择器,分别对应xpath、css,value为值(不能为None) 返回为执行
extract()
之后的结果----列表
例如:
item.add_xpath(‘title’, ‘//*[@class=“item-desc”]/a/@title’)
item.add_css(‘title’, ‘.item-desc>a::atrr(title)’) - processors对应
processors
模块中的方法
processors 中的方法 用来解析选择器返回的数据
==
**分为自定义处理器
和内置处理器
**
处理器分为输入处理器
和输出处理器
在 选择器完成选择时并保存到ItemLoader
对象时,会自动调用输入处理器;在返回给items.py
中定义的Item时
会自动调用输出处理器
- 内置处理器
Join() MapCompose(*function) Takefirst()
1.Join()
将多个结果链接到一起 类似.join()
Join([‘a’, ‘b’]) —> ‘ab’
2.MapCompose(unicode.strip)
去除首尾空白符 类似strip()
MapCompose(unicode.strip)([’ ABC ‘]) —> [‘ABC’]
3.MapCompose(unicode.strip, unicode.title)
去除首尾空白符 并用title格式 (首字母大写,其余小写)
MapCompose(unicode.strip, unicode.title)([‘aCtion’, ‘book’]) —> [‘Action’, ‘Book’]
4.MapCompose(float)
将字符串转成浮点数
MapCompose(float)([‘3.14’]) --> [3.14]
5.Takefirst()
取列表的第一个值
Takefirst()([1, 2, 3]) --> 1
6.MapCompose(lambda x: x.replace(',', ''), float )
去除,
并将字符串转成浮点数
MapCompose(lambda x: x.replace(’,’, ‘’), float)([‘2,3’, ‘3,4’]) --> [23.0, 34.0]
7.MapCompose(lambda x: urljoin(response.url, x) )
拼接url
MapCompose(lambda x: urljoin(‘http://www.test.com’, x))[’/abc’, ‘/zxc’] --> [‘http://www.test.com/abc’, ‘http://www.test.com/zxc’]
**到这里可能有点懵,我们再回顾一下,装载器–> **
item.add_...()
自动执行extract()
extract
得到的为列表,可以先行处理该列表,处理完依然为列表,类似map(fun, list)
,这里调用的是输入处理器input_processor
产出的依然为列表型- 之后要返回
item.load_item()
传回给items.py
中的Item
类, 这里自动调用 输出处理器output_processor
来个小例子 进行测试
from urllib.parse import urljoin
import scrapy
from datashape import unicode
from scrapy.loader import ItemLoader
from scrapy.loader.processors import MapCompose, TakeFirst, Join
from properties.items import PropertiesItem
class LoaderItemLoader(ItemLoader):
default_input_processor = TakeFirst()
# default_output_processor = TakeFirst()
# title_in = TakeFirst()
# title_out = TakeFirst()
# description_out = Join(',')
# description_in = MapCompose(unicode.strip, unicode.title)
# title_out = MapCompose(unicode.title)
# title_in = MapCompose(lambda x: x.replace(' ', '@'))
# description_out = MapCompose(unicode.strip, lambda x: urljoin('http://127.0.0.0/', x))
class LoaderSpider(scrapy.Spider):
name = 'loader'
allowed_domains = ['locahost']
start_urls = ['http://127.0.0.1']
def parse(self, response):
item = LoaderItemLoader(item=PropertiesItem(), response=response)
item.add_value('title', [' first ', ' second', ' third'])
item.add_value('description', [' one', 'two ', 'three'])
yield item.load_item()
方法 | 解释 | 字段 | 结果 |
---|---|---|---|
default_input_processor = TakeFirst() | 默认所有输入处理器 | all | {‘description’: [’ one’], ‘title’: [’ first ']} |
default_output_processor = TakeFirst() | 默认所有输出处理器 | all | {‘description’: ’ one’, ‘title’: ’ first '} |
title_in = Join() description不处理 | 字段输入处理器 | title | {‘description’: [’ one’, ‘two ‘, ‘three’], ‘title’: [’ first second third’]} |
title_out = TakeFirst() description不处理 | 字段输出处理器 | title | {‘description’: [’ one’, 'two ‘, ’ three’], ‘title’: ’ first '} |
title_out = TakeFirst() description_out = Join(’,’) | 字段输出处理器 | title、description | {‘description’: ’ one ,two , three’, ‘title’: ’ first '} |
description_in = MapCompose(unicode.strip, unicode.title) title_out = MapCompose(unicode.title) | 字段输出、输入处理器 | description、title | {‘description’: [‘One’, ‘Two’, ‘Three’], ‘title’: [’ First ‘, ’ Second’, ’ Third’]} |
title_in = MapCompose(lambda x: x.replace(’ ', ‘@’)) description_out = MapCompose(unicode.strip, lambda x: urljoin(‘http://127.0.0.0/’, x)) | 字段输出、输入处理器 | description、title | {‘description’: [‘http://127.0.0.0/one’,‘http://127.0.0.0/two’, ‘http://127.0.0.0/three’],‘title’: [’@first@’, ‘@second’, ‘@third’]} |
额外需要注意的点
- 输入输出处理器可以在
add_xxx(field, value, *processor)
中使用,默认为输入处理器 - 也可以在 定义
Item
时,Item
中使用,例如:uri = scrapy.Field(output_processor=Join())
- 不管如何定义, 顺序一定是 输入处理器—>
LoadItem()
—>输出处理器
相信大家对于这个比较难的点有了一定理解,之后我们会来一个小实战巩固一下,并对比两种生成item方法的使用:
- 常规(存储)
item['title'] = title
- 装载器(处理并存储)
item.add_value('title', 'title') # 大量字段需要抓取时使用更加方便
下一节我们主要讲解scrapy shell 的check功能及url的抽取
(≧∀≦)ゞ