在咱們執行scrapy爬取字段中,會有大量的CSS或是Xpath代碼,當要爬取的網站多了,要維護起來很麻煩,爲解決這類問題,咱們能夠根據scrapy提供的loader機制。css
from scrapy.loader import ItemLoader
要使用Itemloader,必須先將它實例化。查看一下ItemLoader的源碼,有2個重要的傳入參數,item和response數據庫
# 經過ItemLoader對象實例化item item_loader = ItemLoader(item=JobBoleArticleItem(), response=response) # 針對CSS選擇器 item_loader.add_css('title', '.entry-header h1::text') item_loader.add_css('create_date', '.entry-meta .entry-meta-hide-on-mobile::text') item_loader.add_css('praise_num', '.vote-post-up h10::text') item_loader.add_css('collect_num', '.post-adds .bookmark-btn::text') item_loader.add_css('comment_num', '.post-adds .hide-on-480::text') # 針對直接取值的狀況 item_loader.add_value('url', response.url) item_loader.add_value('url_object_id', get_md5(response.url)) item_loader.add_value('front_image_url', [front_image_url]) # 把結果返回給item對象 article_item = item_loader.load_item()
Debug調試查看狀況scrapy
調用默認的item方法目前有2個問題:ide
(1)默認狀況下傳入的都是一些list函數
(2)像parise_num和comment_num傳入的一些值咱們還須要在進行一次過濾,加一些處理函數post
若是解決上面兩個問題?如何取list第一個值,如何在某些字段上加一些處理函數?爲了解決這個問題,咱們須要從新修改items.py,須要導入MapCompose類測試
from scrapy.loader.processors import MapCompose
MapCompose裏面能夠傳入任意多的函數,也能夠傳入一些lambda表達式網站
title = scrapy.Field( # 表明當item傳入值的時候,咱們能夠對這些值進行一些預處理,MapCompose能夠傳入任意多個函數 input_processor = MapCompose(lambda x:x+"-jobbole") )
此時在進行Debug調試,title上會添加-jobboleurl
咱們能夠在加入一個函數,如今MapCompose裏面有一個lambda表達式,一個函數,Debug看是否可以連續處理spa
Debug
經測試能夠從左到右依次連續進行處理
那如何獲取list中的第一個值,此時須要TakeFirst函數
導入
from scrapy.loader.processors import MapCompose, TakeFirst
調用
create_date = scrapy.Field( input_processor = MapCompose(date_convert), output_processor = TakeFirst() )
Debug調試,此時獲取的create_time就是一個date類型的值了而不是一個list
若是全部的字段都去第一個值,是否每一個字段都須要添加
output_processor = TakeFirst()
此時太麻煩,咱們能夠本身定義一個ItemLoader,須要繼承scrapy的ItemLoader類
from scrapy.loader import ItemLoader class ArticleItemLoader(ItemLoader): pass
查看ItemLoader的源碼,有一個默認的
修改默認的default_output_processor方法
class ArticleItemLoader(ItemLoader): default_output_processor = TakeFirst()
在修改咱們爬蟲裏面ItemLoader爲咱們自定義的ItemLoader,在jobbole.py裏面修改
from EnterpriseSpider.items import JobBoleArticleItem, ArticleItemLoader
# 經過ItemLoader對象實例化item item_loader = ArticleItemLoader(item=JobBoleArticleItem(), response=response)
Debug調試,此時item返回的是單個的值而不是一個list
此時返回的front_image_url是一個字符串,此時在交給ImagePipeline進行下載的時候就會拋出異常,咱們必須覆蓋掉默認的output_processor方法
def return_value(value): return value
front_image_url = scrapy.Field( output_processor=MapCompose(return_value) )
此時還須要修改插入數據庫的語句,還須要修改ArticleImagePipeline
class ArticleImagePipeline(ImagesPipeline): def item_completed(self, results, item, info): if "front_image_url" in item: for ok, value in results: image_file_path = value["path"] item["front_image_url"] = image_file_path return item
default_output_processor