python爬蟲之爬取豆瓣電影top250實戰教學

前言:這是我帶領2017級信管班同學學習python爬蟲的第一課,我自學python爬蟲差不多有一年的時間,實戰了大量的網站,對python爬蟲我自己的理解。本來上學期就想帶領大家一起學習的,但是學校的教室不方便申請,加上大家都比較忙,所以未能進行。假期我幫忙很多大四的學生設計畢業論文,他們有很多人做數據挖掘與分析方面的設計,但是自己連什麼是爬蟲?爬蟲可以用來幹什麼?都不理解,寫這方面的論文實在是爲難自己。本學期由於受到疫情的影響,我們只能在家進行網課教學,所以上課的時間很靈活。這個學期曾老師教我們數據分析,如果班上的同學還會使用python爬蟲,無論是在以後論文上,亦或是工作中,都是一大助力,教學力在必行。我使用培訓機構公開課的教學方式,帶領大家使用python爬取《豆瓣電影TOP250》信息進行實戰。我們班開過《web網頁設計基礎》和《大數據技術與運用》兩門課程,正好涵蓋了網絡數據挖掘的基礎,我只需要幫大家搭下橋,帶領大家學懂python爬蟲技能並不難。

視頻鏈接: 騰訊課堂
操作環境: windows10, python37, jupyter, 谷歌瀏覽器
目標網站: 豆瓣電影 Top 250


1、分析網頁

1.1、爲什麼要先分析網頁

當我們拿到一個網頁的時候,第一步並不是去測試它能否能使用 requests 簡單請求到 html ,而是要去選擇合適的方法進行爬取該網頁,弄明白它數據的加載方式,纔可以讓我們的事半功倍,選擇一個好的請求方法也可以提升我們爬蟲程序的效率。

1.2、如何分析網頁結構

我就以該課堂的內容爲例, 進入 豆瓣電影 Top 250,查看它的網頁結構。點擊 “下一頁” ,查看它的URL(鏈接,也叫統一資源定位符),會發現下面的規律:
在這裏插入圖片描述
鏈接測試: 除了第一頁,我們隨便挑選一頁,換直接放在瀏覽器中訪問看看,是否與當前的內容一致,如果沒有問題,就可以直接用訪問鏈接的方式,使用python的requests庫去代替瀏覽器請求網頁的服務器,返回HTML文件,提取並保存信息,再生成下一頁的鏈接,繼續上面請求服務器的操作爬取信息。

生成鏈接:
只需要寫一個for循環,生成從0到225的數字即可,從上面的鏈接可以看出來,它的間隔爲25, for page in range(0, 226, 25) 必須要取超過停止數據225,因爲255不包含在其中,25是它的公差,程序表示爲:
在這裏插入圖片描述



2、請求服務器

接下來就是向服務器發出請求了,我們先選擇第一個鏈接來進行測試,完成本頁所有內容的獲取,然後再獲取所有頁面的信息
請求四部曲:

2.1、導入包 import requests

  • 如果沒有安轉 requests , 可以使用pip直接安轉
  • 步驟:win+r,運行————>cmd,回車,————>pip install requests

2.2、設置瀏覽器代理

  • 網頁點擊右鍵,打開檢查,選擇Network,All,刷新網頁,選擇第一個文件,雙擊,選擇headers
    在這裏插入圖片描述

  • 設置的瀏覽器代理必須爲字典型,如:

headers = {
    'User-Agent':'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/80.0.3987.149 Safari/537.36'
}

2.3、請求服務器格式

  • 請求源代碼,向服務器發出請求,200代表成功
  • 如果在後面加上 .text 表示輸出文本內容
  • test_url 是用一個鏈接,第二個 headers 是用來做瀏覽器代理的內容
requests.get(url = test_url, headers = headers)

2.4、請求服務器代碼彙總

import requests
#pip安轉 pip install requests————>win+r,運行————>cmd,回車,————>pip
test_url = 'https://movie.douban.com/top250?start=0&filter=' #''格式化,爲字符串

#設置瀏覽器代理,它是一個字典
headers = {
    'User-Agent':'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/80.0.3987.149 Safari/537.36'
}

#請求源代碼,向服務器發出請求,200代表成功
reponse = requests.get(url = test_url, headers = headers).text
# 快捷鍵運行,Ctrl+Enter

3、xpath提取信息

xpath是按照HTML標籤的方式進行定位的,谷歌瀏覽器自帶有xpath, 直接複製來就可以使用,簡單方便,運行速度快。

3.1、獲取xpath節點方法

在這裏插入圖片描述

3.2、xpath提取內容

我們使用xpath時,也必須先對網頁進行 lxml 庫中的 etreej解析 ,把它變爲特有的樹狀形式,才能通過它進行節點定位。

from lxml import etree #導入解析庫
html_etree = etree.HTML(reponse) # 看成一個篩子,樹狀

3.2.1、提取文本

當我們提取標籤內的文本時,需要在複製到的xpath後面加上/text() ,告訴它說我需要提取的內容是一個標籤呈現的數據,如《肖申克的救贖》:

<span class="title">肖申克的救贖</span>

xpath爲:

//*[@id="content"]/div/div[1]/ol/li[1]/div/div[2]/div[1]/a/span[1]

提取文字:

name = html_etree.xpath('//*[@id="content"]/div/div[1]/ol/li[1]/div/div[2]/div[1]/a/span[1]/text()')
print ("這是數組形式:",name)
print ("這是字符串形式:",name[0])

結果:

這是數組形式: ['肖申克的救贖']
這是字符串形式: 肖申克的救贖

3.2.2、提取鏈接

每一個鏈接都是在標籤內的,通常放在src=" " 或者 href=" " 之中,如
在這裏插入圖片描述
xpath爲:

//*[@id="content"]/div/div[1]/ol/li[1]/div/div[2]/div[1]/a

提取鏈接:
提取鏈接時,需要在複製到的xpath後面加上/@href , 指定提取鏈接

movie_url = html_etree.xpath('//*[@id="content"]/div/div[1]/ol/li[1]/div/div[2]/div[1]/a/@href')
print ("這是數組形式:",movie_url)
print ("這是字符串形式:",movie_url[0])

結果:

這是數組形式: ['https://movie.douban.com/subject/1292052/']
這是字符串形式: https://movie.douban.com/subject/1292052/

3.2.3、提取標籤元素

這個網頁中電影的星級沒有用幾顆星的文本表示,而是標籤表示的,如:
在這裏插入圖片描述
所以只需要取出 class=" "中的內容就可以得到星級了,複製它的xpath,和提取鏈接的方法一樣,在後面加上 /@class 即可

rating = html_etree.xpath('//*[@id="content"]/div/div[1]/ol/li[1]/div/div[2]/div[2]/div/span[1]/@class')
print ("這是數組形式:",rating)
print ("這是字符串形式:",rating[0])

結果:

這是數組形式: ['rating5-t']
這是字符串形式: rating5-t

4、正則表達式匹配信息

我們需要把結果中的信息匹配出來,可以使用正在表達式,單獨提取自己需要的信息,如星級,它都是以 rating5-t 方式呈現的,但是我們只需要它數字5位置的部分,所以需要進行二次提取

4.1、提取固定位置信息

正則表達式中可以使用 .*? 來進行匹配信息,沒有加括號時可以去掉不一樣的信息,不需要提取出來,加括號 (.*?) 可以提取出括號內的內容,如:

import re
test = "rating5-t"
text = re.findall('rating(.*?)-t', test)
print (text)

結果:

['5']

分析講解:
在這裏插入圖片描述

4.2、匹配出數字

比如評價數,我們xpath提取到的數據格式爲: 1056830人評價 ,保存的時候只需要數字即可,現在把數字提取出來:

import re 
data = "1059232人評價"
num = re.sub(r'\D', "", data)
print("這裏的數字是:", num)

結果:

這裏的數字是: 1059232

5、提取本頁所有信息

我們通過上面的 xpath 只能提取到一條信息,如果我們要提取所有的信息,寫一個 for 循環把它遍歷出來即可

先複製幾個電影名字的 xpath,如前三個的:
在這裏插入圖片描述
li 標籤前的作爲父級,後面的爲子集,./ 代替父級的位置,改寫爲:

li = html_etree.xpath('//*[@id="content"]/div/div[1]/ol/li')
for item in li:
    name = item.xpath('./div/div[2]/div[1]/a/span[1]/text()')[0]
    print (name)

結果:

肖申克的救贖
霸王別姬
阿甘正傳
這個殺手不太冷
美麗人生
泰坦尼克號
千與千尋
辛德勒的名單
盜夢空間
忠犬八公的故事
海上鋼琴師
三傻大鬧寶萊塢
楚門的世界
機器人總動員
放牛班的春天
星際穿越
大話西遊之大聖娶親
熔爐
瘋狂動物城
無間道
龍貓
教父
當幸福來敲門
怦然心動
觸不可及

結果分析: 按照這種方法,就可以遍歷出其中的所有信息


6、內容寫入CSV文件

保存內容與把大象放進冰箱是一樣的,分別爲打卡冰箱,把大象裝進去,關閉冰箱,三部曲:

  1. 打開文件夾
  2. 放進文件夾
  3. 關閉文件夾
import csv
# 創建文件夾並打開
fp = open("./豆瓣top250.csv", 'a', newline='', encoding = 'utf-8-sig')
writer = csv.writer(fp) #我要寫入

# 寫入內容
writer.writerow(('排名', '名稱', '鏈接', '星級', '評分', '評價人數'))

#關閉文件
fp.close()

7、代碼彙總

import requests, csv, re
from lxml import etree

#設置瀏覽器代理,它是一個字典
headers = {
    'User-Agent':'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/80.0.3987.149 Safari/537.36'
}

# 創建文件夾並打開
fp = open("./豆瓣top250.csv", 'a', newline='', encoding = 'utf-8-sig')
writer = csv.writer(fp) #我要寫入
# 寫入內容
writer.writerow(('排名', '名稱', '鏈接', '星級', '評分', '評價人數'))

for page in range(0, 226, 25): #226
    print ("正在獲取第%s頁"%page)
    url = 'https://movie.douban.com/top250?start=%s&filter='%page
    
    #請求源代碼,向服務器發出請求,200代表成功,回退對其,Ctrl+]
    reponse = requests.get(url = url, headers = headers).text
    # 快捷鍵運行,Ctrl+Enter
    html_etree = etree.HTML(reponse) # 看成一個篩子,樹狀
    # 過濾
    li = html_etree.xpath('//*[@id="content"]/div/div[1]/ol/li')
    for item in li:
        #排名
        rank = item.xpath('./div/div[1]/em/text()')[0]
        #電影名稱
        name = item.xpath('./div/div[2]/div[1]/a/span[1]/text()')[0]
        #鏈接
        dy_url = item.xpath('./div/div[2]/div[1]/a/@href')[0]
        #評分
        rating = item.xpath('./div/div[2]/div[2]/div/span[1]/@class')[0]
        rating = re.findall('rating(.*?)-t', rating)[0]
        if len(rating) == 2:
            star = int(rating) / 10  #int()轉化爲數字
        else:
            star = rating
    #     註釋ctrl+?

        rating_num = item.xpath('./div/div[2]/div[2]/div/span[2]/text()')[0]
        content = item.xpath('./div/div[2]/div[2]/div/span[4]/text()')[0]
        content = re.sub(r'\D', "", content)
#         print (rank, name, dy_url, star, rating_num, content)
        # 寫入內容
        writer.writerow((rank, name, dy_url, star, rating_num, content))
fp.close()

jupyter結果截屏:
在這裏插入圖片描述

CSV文件截屏:
在這裏插入圖片描述

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章