之前写了pipelines.py的一些用法:【Scrapy】Scrapy的pipelines管道使用方法 ,主要是用来处理获取数据后做的操作。
而这次介绍的items.py,它的作用主要是用来处理获取的的数据,做数据清洗用的,具体也很难一时讲清,先看代码。
1.首先我们通过ItemLoader 获取到数据
import sys
sys.path.append(r'E:\projects\python-spider')
import scrapy
from scrapy.loader import ItemLoader
from spiderJob.items import SpiderjobItem
def getUrl():
return 'https://search.51job.com/list/030200,000000,0000,00,9,99,%2520,2,1.html?lang=c&stype=&postchannel=0000&workyear=99&cotype=99°reefrom=99&jobterm=99&companysize=99&providesalary=99&lonlat=0%2C0&radius=-1&ord_field=0&confirmdate=9&fromType=&dibiaoid=0&address=&line=&specialarea=00&from=&welfare='
class itemSpider(scrapy.Spider):
name = 'argsSpider'
def start_requests(self):
url = getUrl()
yield scrapy.Request(url, self.parse) # 发送请求爬取参数内容
def parse(self, response):
mingyan = response.css('div#resultList>.el') # 提取首页所有数据,保存至变量mingyan
for index ,v in enumerate(mingyan): # 循环获取
if(index > 0):
load = ItemLoader(item= SpiderjobItem(), selector=v)
load.add_css("t1", ".t1 a::text")
load.add_css("t2", ".t2 a::attr(title)")
load.add_css("t3", ".t3::text")
load.add_css("t4", ".t4::text")
item = load.load_item()
yield item;
2.处理并返回
import scrapy
# ItemLoader
# 是分离数据的另一种方式,可以将数据的分离和提取分为两部分,
# 默认使用xpath, css数据提取方式,
# 让代码更加整洁,更加清晰。
from scrapy.loader import ItemLoader
from scrapy.loader.processors import *
# 如果list为空则不会进行处理,这种情况需要重载MapCompose类的__call__方法
class MapComposeCustom(MapCompose):
#自定義MapCompose,當value沒元素時傳入" "
def __call__(self, value, loader_context=None):
if not value:
value.append(" ")
values = arg_to_iter(value)
if loader_context:
context = MergeDict(loader_context, self.default_loader_context)
else:
context = self.default_loader_context
wrapped_funcs = [wrap_loader_context(f, context) for f in self.functions]
for func in wrapped_funcs:
next_values = []
for v in values:
next_values += arg_to_iter(func(v))
values = next_values
return values
#TakeFirst来作为默认输出处理器,但该函数会筛掉空字符,因此重载该类的__call__
class TakeFirstCustom(TakeFirst):
def __call__(self, values):
for value in values:
if value is not None and value != '':
return value.strip() if isinstance(value, str) else value
# 过滤空格
def cutSpace(value):
result = str(value).replace(" ","");
result = str(result).replace("\n", "");
result = str(result).replace("\r", "");
return result
class SpiderjobItem(scrapy.Item):
t1 = scrapy.Field(
input_processor=MapComposeCustom(cutSpace),
output_processor=Join()
) # 标题
t2 = scrapy.Field(
input_processor = MapComposeCustom(cutSpace),
output_processor = Join()
) # 标题
t3 = scrapy.Field(
input_processor = MapComposeCustom(cutSpace),
output_processor = Join()
) # 标题
t4 = scrapy.Field(
input_processor=MapComposeCustom(cutSpace),
output_processor=Join()
) # 标题
pass
这里遇到几个坑:
1.一开始我用的并不是 MapComposeCustom ,而是 MapCompose ,但是为什么之后改了? 因为它不能处理传入来的数据为空导致会出现下面的情况,有些项没有了,我获取item['1']报错了,所以通过重载MapCompose方法的__call__,处理这个情况。而TakeFirstCustom我没用到,但别人一般都会用到,我就也列出来。
{
't1':['1'],
't2':['1'],
't3':['1'],
't4':['1'],
},
{
't2':['1'],
't3':['1'],
}
2.用为什么要用上Join()
因为返回的是t1等是数组,而我需要的是字符串。