1. 程式人生 > 其它 >豆瓣top250影視劇爬蟲(含完整程式碼)

豆瓣top250影視劇爬蟲(含完整程式碼)

目錄

流程

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()

效果展示

參考

Python爬蟲程式設計基礎5天速成(2021全新合集)Python入門+資料分析_嗶哩嗶哩_bilibili