使用Item Loaders對Item資料進行提取和解析(整理)
阿新 • • 發佈:2019-01-24
1.當建立item物件(item=JobboleItem())的時候, 會去Item.py檔案中初始化對應的input/output_processor處理器
2.當item中的處理器初始化完成, 回到bole.py爬蟲檔案中, 建立item_loader物件
3.item_loader物件建立完成, 開始通過add_xpath/add_css/add_value收集資料
4.每收集一個數據, 就會將該資料傳遞給對應欄位的inout_processor繫結的函式進行資料處理, 資料處理完成, 會暫時儲存在ItemLoader中
5迴圈第四步, 將每一個欄位的資料提取並交給input_processor, 直到所有資料提取完畢, 所有資料都會被儲存在ItemLoader中
6.呼叫load_item()函式, 給item物件進行賦值
bole.py:
from jobbole.items import JobboleItem
from scrapy.loader import ItemLoader
item_loader = ItemLoader(item=JobboleItem(), response=response) item_loader.add_xpath('title', '//div[@class="entry-header"]/h1/text()') item_loader.add_xpath('date_time', '//p[@class="entry-meta-hide-on-mobile"]/text()') item_loader.add_xpath('tags', '//p[@class="entry-meta-hide-on-mobile"]/a/text()') item_loader.add_xpath('content', '//div[@class="entry"]//text()') item_loader.add_xpath('zan_num', '//div[@class="post-adds"]/span[contains(@class, "vote-post-up")]//text()') item_loader.add_xpath('keep_num', '//div[@class="post-adds"]/span[contains(@class, "bookmark-btn")]/text()') item_loader.add_xpath('comment_num', '//div[@class="post-adds"]/a/span/text()') item_loader.add_value('img_src', [response.meta['img_src']]) item = item_loader.load_item() yield item
items.py:
import scrapy, re from datetime import datetime from scrapy.contrib.loader.processor import Join, MapCompose, TakeFirst # 函式中的引數value值,是add_xpath/add_css/add_value傳過來的列表資料中的每一個元素。 # def input_test_title(value): # return value + '====' # # def output_test_title(value): # return '---' + value # # def result(value): # # 這裡面join拼接的大列表裡的一個元素 # return ''.join(value) def convert_datetime(value): # 將字串型別轉化成datetime型別 value = value.replace('·', '').strip() try: # strptime(時間字串,轉化後的格式): 函式返回值是datetime型別的物件 date_time = datetime.strptime(value, '%Y/%m/%d') except: # 如果轉化失敗,將當前時間作為預設值。 date_time = datetime.now() return date_time def convert_tags(value): # ['自由職業', '1 評論', '職業'] # 過濾 "評論" if "評論" in value: return "" return value def zan_number(value): if value.strip() != "": pattern = re.compile(r'\d+') num = re.findall(pattern, value) if num: num = int(num[0]) else: num = 0 return num def get_number(value): # 提取評論、點贊數 pattern = re.compile(r'\d+') num = re.findall(pattern, value) if num: num = int(num[0]) else: num = 0 return num def process_image(value): # 拼接圖片地址 return value class JobboleItem(scrapy.Item): title = scrapy.Field( # MapCompose對映類,可以將ItemLoader傳遞過來的列表中的元素,依次作用到test_title函式上,類似於map()函式。 # input_processor=MapCompose(input_test_title), # Join(): 對列表進行合併,add_xpath/add_css/add_value傳過來的列表資料。 # output_processor=TakeFirst() ) date_time = scrapy.Field( input_processor=MapCompose(convert_datetime), # TakeFirst(): 獲取列表中的首個元素 # output_processor=TakeFirst() ) tags = scrapy.Field( input_processor=MapCompose(convert_tags), # 覆蓋預設的default_output_processor = TakeFirst() output_processor=Join() ) content = scrapy.Field( output_processor=Join() ) zan_num = scrapy.Field( # ['', '1', ' 贊'] input_processor=MapCompose(zan_number), # output_processor=TakeFirst() ) keep_num = scrapy.Field( input_processor=MapCompose(get_number), # output_processor=TakeFirst() ) comment_num = scrapy.Field( input_processor=MapCompose(get_number), # output_processor=TakeFirst() ) # 圖片的源地址 img_src = scrapy.Field() # 圖片在本地的下載路徑, 該欄位只有在圖片下載完成以後,才能進行賦值。 img_path = scrapy.Field()
實現自定義的圖片修改:
from scrapy.contrib.loader import ItemLoader
class CustomItemloader(ItemLoader):
"""
實現自定義的ItemLoader,可以指定預設的output_processor的值。可以避免在每一個欄位中,設定重複的值。
"""
default_output_processor = TakeFirst()