iT邦幫忙

2019 iT 邦幫忙鐵人賽

DAY 19
1
AI & Data

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

[Day 19] 實戰:Scrapy爬旅遊新聞文章(2)

嗨!昨天介紹了Spider爬取新聞內容,今天要說明如何透過pipeline將資料存到MySQL資料庫,也提到dotenv如何使用!

  • 什麼是dotenv? 一般來說我們會將較敏感的資訊放在.env檔案內,不會直接寫在程式碼中,像是資料庫的位址或帳號密碼等。

可以直接到 GitHub - theskumar/python-dotenv 查看範例如何操作,這邊我會直接使用不詳細說明哦。

  • 在專案底下建立.env
vim .env

接下來寫入內容到.env檔案(請寫上你自己的不要直接貼上啊~):

MYSQL_DB_NAME = 'MYSQL_DB_NAME'
MYSQL_DB_HOST = 'localhost'
MYSQL_PORY = 3306
MYSQL_USER = 'MYSQL_USER'
MYSQL_PASSWORD = 'MYSQL_PASSWORD'
  • 建立資料表:
create table news (
    id int AUTO_INCREMENT, 
    title text,
    content text,
    img text,
    time text, 
    primary key(id)
)

確定好資料庫的設定以及.env設定之後:

  • 打開settings.py檔案:
from dotenv import load_dotenv, find_dotenv
import os
load_dotenv(find_dotenv())
MYSQL_DB_NAME = os.getenv("MYSQL_DB_NAME")
MYSQL_DB_HOST = os.getenv("MYSQL_DB_HOST")
MYSQL_PORY = os.getenv("MYSQL_PORY")
MYSQL_USER = os.getenv("MYSQL_USER")
MYSQL_PASSWORD = os.getenv("MYSQL_PASSWORD")
print('Connect to db ::', MYSQL_DB_HOST, MYSQL_DB_NAME)
  • 執行看到:

Imgur
表示有載入.env的內容了!

如果是空值,請確定自己使用的是python3版本,之前試發現python2版本似乎沒有支援了!

好了之後就可以來寫pipelines.py了,需要將爬到的內容存到資料庫,所以建立一個MySqlPipelineClass

class MySqlPipeline(object):
    def open_spider(self, spider):
        pass
    def close_spider(self, spider):
        pass
    def process_item(self, item, spider):
        pass
    def insert_to_mysql(self, item):
        pass
  • 要透過python連接資料庫可以使用pymysql
import pymysql
  • 定義open_spider(),讓spider被開啟會連接MySQL
def open_spider(self, spider):
        # Database Settings
        db = spider.settings.get('MYSQL_DB_NAME')
        host = spider.settings.get('MYSQL_DB_HOST')
        port = spider.settings.get('MYSQL_PORY')
        user = spider.settings.get('MYSQL_USER')
        password = spider.settings.get('MYSQL_PASSWORD')
        # Database Connecting
        self.connection = pymysql.connect(
            host = host,
            user = user,
            password= password,
            db = db,
            cursorclass= pymysql.cursors.DictCursor
        )
  • 爬完後關閉連線:
def close_spider(self, spider):
    self.connection.close()
  • 為了避免抓到重複的文章,我們多定義一個filter_repeat_data的function,若沒有重複則呼叫insert_to_mysql
old_data_from_sql = []
def filter_repeat_data(self, item):
        # Getting Old Data from DB
        with self.connection.cursor() as cursor:
            sql = "SELECT * FROM news"
            cursor.execute(sql)
            for row in cursor:
                self.old_data_from_sql.append(row['title'])
        
        if item['title'] not in self.old_data_from_sql:
            self.insert_to_mysql(item)
  • 接著定義insert_to_mysql用來把資料到資料庫:
def insert_to_mysql(self, item):
        values = (
            item['title'],
            item['content'],
            item['img'],
            item['time'],
        )
        with self.connection.cursor() as cursor:
            sql = 'INSERT INTO `news` (`title`, `content`, `img`, `time`) VALUES (%s, %s, %s, %s)'
            cursor.execute(sql, values)
            self.connection.commit()
  • 每抓到一筆新聞,就查看是否重複:
def process_item(self, item, spider):
    self.filter_repeat_data(item)
    return item

這樣就定義完pipeline了,最後我們不能忘記最重要的步驟,到settings.py開啟ITEM_PIPELINES

ITEM_PIPELINES = {
   'traNews.pipelines.MySqlPipeline': 300,
}

最後,執行程式碼查看資料庫是否有資料新增了:

select * from news

Imgur

好的,這樣整個流程就完成了,我也將程式碼放到我的 GitHub - plusoneee
(不過Spider的部分可能會有些許的不同) 今天就到這裡了!明天見!


上一篇
[Day 18] 實戰:Scrapy爬旅遊新聞文章(1)
下一篇
[Day 20] Scrapy 模擬登入
系列文
Scrapy爬蟲與資料處理30天筆記30

尚未有邦友留言

立即登入留言