1. 程式人生 > >scrapy爬蟲資料存入mysql資料庫

scrapy爬蟲資料存入mysql資料庫

上篇部落格使用scrapy框架爬取豆瓣電影top250資訊將各種資訊通過json存在檔案中,不過對資料的進一步使用顯然放在資料庫中更加方便,這裡將資料存入mysql資料庫以便以後利用。
執行環境:

 1. win7-64bit
 2. python 3.5.3
 3. mysql 5.7.17

安裝mysql資料庫模組

開啟命令列輸入python後,通過import MySQLdb檢查是否支援mysql資料庫

這裡寫圖片描述

出現錯誤
ImportError: No module named MySQLdb
那麼就要手動安裝,查詢發現mysqldb只支援到python3.4,這裡選擇使用pymysql,通過

這裡下載後解壓,切換到PyMySQL3-0.5目錄,通過shift+滑鼠右鍵選擇在此處開啟命令視窗,輸入命令python setup.py install安裝

這裡寫圖片描述

安裝結束後,測試是否可以使用

這裡寫圖片描述

安裝成功!

建立資料庫和表

由於上篇部落格中爬取的資料屬性就是對應的MovieItem屬性

class MovieItem(scrapy.Item):
    # 電影名字
    name = scrapy.Field()
    # 電影資訊
    info = scrapy.Field()
    # 評分
    rating = scrapy.Field()
    # 評論人數
num = scrapy.Field() # 經典語句 quote = scrapy.Field() # 電影圖片 img_url = scrapy.Field()

據此建立資料庫表,建立資料庫的時候加上DEFAULT CHARACTER SET utf8 COLLATE utf8_general_ci,以防出現亂碼

create database douban DEFAULT CHARACTER SET utf8 COLLATE utf8_general_ci;
use douban;
CREATE TABLE doubanmovie (
    name VARCHAR
(100) NOT NULL, # 電影名字 info VARCHAR(150), # 電影資訊 rating VARCHAR(10), # 評分 num VARCHAR(10), # 評論人數 quote VARCHAR(100), # 經典語句 img_url VARCHAR(100), # 電影圖片 )

儲存資料

首先在專案settings檔案中新增與資料庫連線相關的變數

MYSQL_HOST = 'localhost'
MYSQL_DBNAME = 'douban'
MYSQL_USER = 'root'
MYSQL_PASSWD = '123456'

在MoviePipelines.py檔案中建立類DBPipeline,在其中進行對資料庫的操作。
首先連線資料庫,獲取cursor以便之後對資料就行增刪查改

    def __init__(self):
        # 連線資料庫
        self.connect = pymysql.connect(
            host=settings.MYSQL_HOST,
            db=settings.MYSQL_DBNAME,
            user=settings.MYSQL_USER,
            passwd=settings.MYSQL_PASSWD,
            charset='utf8',
            use_unicode=True)

        # 通過cursor執行增刪查改
        self.cursor = self.connect.cursor();

注意這裡charset屬性為 ‘utf8’,中間沒有-,在除錯過程中因為這個-搞了半天

之後過載方法process_item(self, item, spider),在其中執行資料的增刪查改,通過cursor編寫sql語句,然後使用self.connect.commit()提交sql語句

    def process_item(self, item, spider):
        try:
            # 插入資料
            self.cursor.execute(
                """insert into doubanmovie(name, info, rating, num ,quote, img_url)
                value (%s, %s, %s, %s, %s, %s)""",
                (item['name'],
                 item['info'],
                 item['rating'],
                 item['num'],
                 item['quote'],
                 item['img_url']))

            # 提交sql語句
            self.connect.commit()

        except Exception as error:
            # 出現錯誤時列印錯誤日誌
            log(error)
        return item

最後在settings檔案中註冊DBPipeline

ITEM_PIPELINES = {
    'doubanmovie.MoviePipelines.MoviePipeline': 1,
    'doubanmovie.ImgPipelines.ImgPipeline': 100,
    'doubanmovie.MoviePipelines.DBPipeline': 10,
}

大功告成後,嘗試執行,然而爬取的資料是250條,在資料庫儲存中只有239條

這裡寫圖片描述
查看出錯日誌,發現有以下錯誤

pymysql.err.ProgrammingError: (1064, "You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near '), 'https://img3.doubanio.com/view/movie_poster_cover/ipst/public/p2255040492.jp' at line 2")
TypeError: 'module' object is not callable

又是半天折騰,忽然想起來電影的quote屬性可能不存在,檢視MySpider.py檔案,發現果然如此

quote = movie.xpath('.//span[@class="inq"]/text()').extract()
if quote:
    quote = quote[0].strip()
item['quote'] = quote

如果網頁中quote屬性不存在,那麼將item插入資料庫時就會出錯,增加一條else語句

if quote:
    quote = quote[0].strip()
else:
    quote = ' '
item['quote'] = quote

再次執行爬蟲後,檢視資料庫,沒錯,果然這次多了250條資料,資料總數由239變成489

這裡寫圖片描述

資料查重處理

不過每次執行,重複資料都會多存一次,而我們想要的是多次執行,重複資料只存一遍就好了,那麼就要增加查重處理。
這裡使用self.cursor.fetchone()方法來判斷有沒有重複資料,在每次插入資料前,先判斷插入item是否已在表中。通過屬性img_url查詢該item在表中是否存在,如果存在,執行定義的操作,簡單起見,這裡直接丟掉了,不過可以執行update語句對資料進行更新。

# 查重處理
self.cursor.execute(
    """select * from doubanmovie where img_url = %s""",
    item['img_url'])
# 是否有重複資料
repetition = self.cursor.fetchone()

# 重複
if repetition:
    pass

增加處理後,多次執行爬蟲,資料庫中不再有重複資料。

這裡寫圖片描述

最後整個DBPipeline類程式碼如下

# 用於資料庫儲存
class DBPipeline(object):
    def __init__(self):
        # 連線資料庫
        self.connect = pymysql.connect(
            host=settings.MYSQL_HOST,
            port=3306,
            db=settings.MYSQL_DBNAME,
            user=settings.MYSQL_USER,
            passwd=settings.MYSQL_PASSWD,
            charset='utf8',
            use_unicode=True)

        # 通過cursor執行增刪查改
        self.cursor = self.connect.cursor();

    def process_item(self, item, spider):
        try:
            # 查重處理
            self.cursor.execute(
                """select * from doubanmovie where img_url = %s""",
                item['img_url'])
            # 是否有重複資料
            repetition = self.cursor.fetchone()

            # 重複
            if repetition:
                pass

            else:
                # 插入資料
                self.cursor.execute(
                    """insert into doubanmovie(name, info, rating, num ,quote, img_url)
                    value (%s, %s, %s, %s, %s, %s)""",
                    (item['name'],
                     item['info'],
                     item['rating'],
                     item['num'],
                     item['quote'],
                     item['img_url']))

            # 提交sql語句
            self.connect.commit()

        except Exception as error:
            # 出現錯誤時列印錯誤日誌
            log(error)
        return item

基本的資料庫儲存功能算是實現了,雖然足夠簡單,不過在寫的過程中也遇到很多坑,還是要不斷百度google來處理遇到的問題。實現資料庫儲存之後,就可以多爬一些其他資料,然後合理運用一下,搞一些自己的小專案來玩一下