iT邦幫忙

2019 iT 邦幫忙鐵人賽

DAY 16
0
AI & Data

Scrapy爬蟲與資料處理30天筆記系列 第 16

[Day 16] Scrapy Item Pipeline 應用

嗨,在上一篇文章中已經說明了Item Pipelineprocess_item()的使用,接下來我們來看看其他的方法吧,除了process_item()為必要的,其它的像是open_spider(spider), close_spider(spider)皆為選用的:

  • open_spider(spider): 當spider被打開時啟用
  • close_spider(spider): 當spider被關閉時啟用

昨天,輸出成檔案之後可以發現若文章被刪除了標題就會為空值null(例如:{"push": 1, "title": null, "href": null, "date": "10/24", "author": "-"} 的一筆資料。)
那要怎麼去除被刪除的文章呢?

開啟pipelines.py檔案,在最上面增加:

from scrapy.exceptions import DropItem

為了確保輸出的資料內容不會為null,我們新增一個類別DeleteNullTitlePipeline來實做過濾空值資料,程式碼:

class DeleteNullTitlePipeline(object):
    def process_item(self, item, spider):
        title = item['title'] 
        if title:
            return item
        else:
            raise DropItem('found null title %s', item)
  • 每當Pipeline接收到一篇文章時,便去判斷它是否為空值,若為空值則透過DropItem()這個處理例外的方法將Item去掉,若有值再回傳item。

別忘了一個很重要的事情!
就是要啟用DeleteNullTitlePipeline,不然會發現怎麼執行結果都沒變。

  • 開啟settings.py檔案
  • 增加'myFirstScrapyProject.pipelines.DeleteNullTitlePipeline': 200,如下:
ITEM_PIPELINES = {
'myFirstScrapyProject.pipelines.MyfirstscrapyprojectPipeline': 300,
'myFirstScrapyProject.pipelines.DeleteNullTitlePipeline': 200,
}

再執行程式碼:

scrapy crawl ptt -o ptt.json

若收到空值則會看到爬蟲的log出現警告:

[scrapy.core.scraper] WARNING: Dropped: ('found null title %s', {'author': '-', 'date': '10/23', 'href': None, 'push': None,'title': None})
{'author': '-', 'date': '10/23', 'href': None, 'push': None, 'title': None}
  • 打開ptt.json應該會發現裡面沒有"title":null的資料了!

現在說明如何過濾重複的資料:

  • 新增一個DuplicatesTitlePipeline的類別。
  • 建立一個叫做article的集合。
  • 若發現title已經存在於集合內則丟棄該item,否則丟入集合內並傳回item。
class DuplicatesTitlePipeline(object):
    def __init__(self):
        self.article = set()
    def process_item(self, item, spider):
        title = item['title'] 
        if title in self.article:
            raise DropItem('duplicates title found %s', item)
        self.article.add(title)
        return(item)

最重要的當然是啟用DuplicatesTitlePipeline

  • Pipeline新增'myFirstScrapyProject.pipelines.DuplicatesTitlePipeline': 211
ITEM_PIPELINES = {
   'myFirstScrapyProject.pipelines.MyfirstscrapyprojectPipeline': 300,
   'myFirstScrapyProject.pipelines.DeleteNullTitlePipeline': 200,
   'myFirstScrapyProject.pipelines.DuplicatesTitlePipeline': 400,
}

這樣就完成了!

  • 不過本篇的例子為爬PTT版,可能就不適合單用title來過濾重複,因為通常回文的標題都是一樣的,這樣會不小心把文章都過濾掉了,所以要確定好需求再去寫pipelines哦!

今天說明了透過Pipeline過濾重複資料, 刪除不存在文章,接下來會說明如何將資料透過Pipeline存入不同的資料庫中。

今天就到這裡了,明天見啦!


上一篇
[Day 15] Scrapy Item Pipeline 操作
下一篇
[Day 17] Scrapy Item Pipeline 存入資料庫
系列文
Scrapy爬蟲與資料處理30天筆記30

尚未有邦友留言

立即登入留言