豆瓣top250影視劇爬蟲(含完整程式碼)
阿新 • • 發佈:2022-04-12
目錄
流程
graph LR A(模擬傳送請求) --> B(獲取並解析資料) B --> C(建立資料庫) C-->d(儲存資料)目標網站 https://movie.douban.com/top250?start=
模擬傳送請求
呼叫urllib庫
URL(Uniform Resource Locator ):統一資源定位符,是網頁存放檔案的地址
head:請求頭,告訴你要訪問的網站請求是誰發出的,也就是我們的裝置資訊
Google瀏覽器->快捷鍵F12(開發者模式)
請求頭內容在下圖藍色方框所示位置
import urllib.request, urllib.error # 指定URL,獲取網頁資料 def askURL(url): head = {" "} #請填入上圖中藍框內程式碼(user agent資訊) request = urllib.request.Request(url, headers=head) html = "" # 異常處理 try: response = urllib.request.urlopen(request) html = response.read().decode("utf-8") # print(html) except urllib.error.URLError as e: if hasattr(e,"code"): print(e.code) if hasattr(e,"reason"): print(e.reason) return html
獲取並解析資料
- 呼叫BeautifulSoup庫和re庫
- BeautifulSoup:“靚湯”,把我們爬取的資訊資源熬成靚湯
- re(regular expression):正則表示式,能夠根據關鍵詞或句式,對文字資訊進行搜尋匹配
from bs4 import BeautifulSoup # 網頁解析, 獲取資料(拆分) import re # 正則表示式,進行文字匹配(提煉) #獲取資料 def getData(baseurl): datalist = [] for i in range(0,10): url = baseurl + str(i*25) html = askURL(url) #儲存網頁原始碼 # 逐一解析資料 soup = BeautifulSoup(html,"html.parser") for item in soup.find_all('div',class_="item"): # 查詢符合要求字串,形成列表 data = [] item = str(item) link = re.findall(findLink,item)[0] # re庫通過正則表示式查詢指定字串 data.append(link) # 新增連結 ImgSrc = re.findall(findImgSrc,item)[0] # 新增圖片 data.append(ImgSrc) titles = re.findall(findTitle, item) # 新增片名 if(len(titles)==2): ctitle = titles[0] otitle = titles[1].replace("/","") otitle = re.sub(r'\xa0',"",otitle) # re.sub替換指定字元 data.append(ctitle) data.append(otitle) else: ctitle = titles[0] data.append(ctitle) data.append(' ') rating = re.findall(findRating,item)[0] # 新增評分 data.append(rating) judgeNum = re.findall(findJudge,item)[0] # 新增評論人數 data.append(judgeNum) inq = re.findall(findInq,item) # 新增簡介 if len(inq) != 0: inq = inq[0].replace("。","") data.append(inq) else: data.append(" ") bd = re.findall(findBd,item)[0] bd = re.sub('<br(\s+)?/>(\s+)?'," ",bd) bd = re.sub('/'," ",bd) bd = re.sub(r'\xa0', "", bd) data.append(bd.strip()) # strip()去頭尾 datalist.append(data) # print(datalist) return datalist
- 調出獲取到的html檔案,根據文字特點,設計正則表示式
# html檔案 <div class="item"> <div class="pic"> <em class="">1</em> <a href="https://movie.douban.com/subject/1292052/"> <img alt="肖申克的救贖" class="" src="https://img2.doubanio.com/view/photo/s_ratio_poster/public/p480747492.jpg" width="100"/> </a> </div> <div class="info"> <div class="hd"> <a class="" href="https://movie.douban.com/subject/1292052/"> <span class="title">肖申克的救贖</span> <span class="title"> / The Shawshank Redemption</span> <span class="other"> / 月黑高飛(港) / 刺激1995(臺)</span> </a> <span class="playable">[可播放]</span> </div> <div class="bd"> <p class=""> 導演: 弗蘭克·德拉邦特 Frank Darabont 主演: 蒂姆·羅賓斯 Tim Robbins /...<br/> 1994 / 美國 / 犯罪 劇情 </p> <div class="star"> <span class="rating5-t"></span> <span class="rating_num" property="v:average">9.7</span> <span content="10.0" property="v:best"></span> <span>2591411人評價</span> </div> <p class="quote"> <span class="inq">希望讓人自由。</span> </p> </div> </div> </div>
# 正則表示式 findLink = re.compile(r'<a href="(.*?)">') #建立正則表示式物件,表示規則 findImgSrc = re.compile(r'<img.*src="(.*?)"', re.S) # .一個 *多個 ?貪婪(搜尋到第一個就停止) findTitle = re.compile(r'<span class="title">(.*)</span>') findRating = re.compile(r'<span class="rating_num" property="v:average">(.*)</span>') findJudge = re.compile(r'<span>(\d*)人評價</span>') findInq = re.compile(r'<span class="inq">(.*)</span>') findBd = re.compile(r'<p class="">(.*?)</p>', re.S) # re.S 換行不重新匹配 字串整體進行匹配
建立資料庫
呼叫sqlite3資料庫
import sqlite3 # SQLite資料庫操作 # 建立資料庫 def init_db(dbpath): sql = ''' # 建立資料表 create table if not exists movie250 ( id integer primary key autoincrement, info_link text, pic_link text, cname varchar, ename varchar, score numeric, rated numeric, instroduction text, info text ) ''' conn = sqlite3.connect(dbpath) # 開啟或建立資料庫檔案 cursor = conn.cursor() # 獲取遊標 cursor.execute(sql) # 執行sql語句 conn.commit() # 提交資料庫操作 conn.close() # 關閉資料庫連線
儲存資料
# 儲存資料 def saveData2DB(datalist,dbpath): init_db(dbpath) conn = sqlite3.connect(dbpath) cur = conn.cursor() for data in datalist: for index in range(len(data)): # data[index] = '"' + str(data[index]) + '"' if index == 4 or index == 5: continue data[index] = '"'+data[index]+'"' sql = ''' insert into movie250( info_link,pic_link,cname,ename,score,rated,instroduction,info) values(%s)'''%",".join(data) # 逗號連線 print(sql) cur.execute(sql) conn.commit() cur.close() conn.close()
完整程式碼
# -*- coding = utf-8 -*-
# @Time : 2022-04-06 上午 12:15
# @Author : SYSUer
# @File : crawler.py
# @Software : PyCharm
# 學習參考 https://www.bilibili.com/video/BV12E411A7ZQ?p=15
from bs4 import BeautifulSoup # 網頁解析, 獲取資料(拆分)
import re # 正則表示式,進行文字匹配(提煉)
import urllib.request, urllib.error # 指定URL,獲取網頁資料
import sqlite3 # SQLite資料庫操作
def main():
baseurl = "https://movie.douban.com/top250?start="
# 1.爬取網頁
datalist = getData(baseurl)
# savepath = ".\\豆瓣電影Top250.xls"
dbpath = "movie.db"
# 3.儲存資料
# saveData(savepath)
saveData2DB(datalist,dbpath)
findLink = re.compile(r'<a href="(.*?)">') #建立正則表示式物件,表示規則
findImgSrc = re.compile(r'<img.*src="(.*?)"', re.S) # .一個 *多個 ?貪婪(搜尋到第一個就停止)
findTitle = re.compile(r'<span class="title">(.*)</span>')
findRating = re.compile(r'<span class="rating_num" property="v:average">(.*)</span>')
findJudge = re.compile(r'<span>(\d*)人評價</span>')
findInq = re.compile(r'<span class="inq">(.*)</span>')
findBd = re.compile(r'<p class="">(.*?)</p>', re.S) # re.S 換行不重新匹配 字串整體進行匹配
# 爬取網頁
def getData(baseurl):
datalist = []
for i in range(0,10):
url = baseurl + str(i*25)
html = askURL(url) #儲存網頁原始碼
# 逐一解析資料
soup = BeautifulSoup(html,"html.parser")
for item in soup.find_all('div',class_="item"): # 查詢符合要求字串,形成列表
data = []
item = str(item)
link = re.findall(findLink,item)[0] # re庫通過正則表示式查詢指定字串
data.append(link) # 新增連結
ImgSrc = re.findall(findImgSrc,item)[0] # 新增圖片
data.append(ImgSrc)
titles = re.findall(findTitle, item) # 新增片名
if(len(titles)==2):
ctitle = titles[0]
otitle = titles[1].replace("/","")
otitle = re.sub(r'\xa0',"",otitle) # re.sub替換指定字元
data.append(ctitle)
data.append(otitle)
else:
ctitle = titles[0]
data.append(ctitle)
data.append(' ')
rating = re.findall(findRating,item)[0] # 新增評分
data.append(rating)
judgeNum = re.findall(findJudge,item)[0] # 新增評論人數
data.append(judgeNum)
inq = re.findall(findInq,item) # 新增簡介
if len(inq) != 0:
inq = inq[0].replace("。","")
data.append(inq)
else:
data.append(" ")
bd = re.findall(findBd,item)[0]
bd = re.sub('<br(\s+)?/>(\s+)?'," ",bd)
bd = re.sub('/'," ",bd)
bd = re.sub(r'\xa0', "", bd)
data.append(bd.strip()) # strip()去頭尾
datalist.append(data)
# print(datalist)
return datalist
def askURL(url):
head = {" "} #請填入user agent資訊
request = urllib.request.Request(url, headers=head)
html = ""
# 異常處理
try:
response = urllib.request.urlopen(request)
html = response.read().decode("utf-8")
# print(html)
except urllib.error.URLError as e:
if hasattr(e,"code"):
print(e.code)
if hasattr(e,"reason"):
print(e.reason)
return html
# 儲存資料
def saveData2DB(datalist,dbpath):
init_db(dbpath)
conn = sqlite3.connect(dbpath)
cur = conn.cursor()
for data in datalist:
for index in range(len(data)):
# data[index] = '"' + str(data[index]) + '"'
if index == 4 or index == 5:
continue
data[index] = '"'+data[index]+'"'
sql = '''
insert into movie250(
info_link,pic_link,cname,ename,score,rated,instroduction,info)
values(%s)'''%",".join(data) # 逗號連線
print(sql)
cur.execute(sql)
conn.commit()
cur.close()
conn.close()
# 建立資料表
def init_db(dbpath):
sql = '''
create table if not exists movie250
(
id integer primary key autoincrement,
info_link text,
pic_link text,
cname varchar,
ename varchar,
score numeric,
rated numeric,
instroduction text,
info text
)
'''
conn = sqlite3.connect(dbpath) # 開啟或建立資料庫檔案
cursor = conn.cursor() # 獲取遊標
cursor.execute(sql) # 執行sql語句
conn.commit() # 提交資料庫操作
conn.close() # 關閉資料庫連線
if __name__ == '__main__': # 當程式執行時
# 呼叫函式
init_db("movietest.db")
main()