之前寫了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等是數組,而我需要的是字符串。