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,通過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來處理遇到的問題。實現資料庫儲存之後,就可以多爬一些其他資料,然後合理運用一下,搞一些自己的小專案來玩一下