Python 爬取豆瓣電影 TOP 250
豆瓣作為一個匯聚書影音內容的社群網站,得到了大量使用者的認可和青睞,現在很年輕人在看電影或者買書之前都會去豆瓣上看一下評分和相關評論,不得不說豆瓣評分在一定程度上很客觀的反映了一部作品的受歡迎程度。
今天,我們就抓取下豆瓣電影 top 250 的相關資料。
首先需要先明確下我們所需要獲取的資訊如下:名稱,導演,國家,連結,上映時間,型別,評分(五星,四星佔比)以及評價人數。
分析網址
首先我們觀察下豆瓣電影 top 250 的網址變化後會發現,top 250 共計分為 10 頁,每一頁 25 條記錄,網址為
https://movie。douban。com/top250?start={start}&filter=
其中 start 從 0 開始,每次遞增 25,到 225 結束,相信大家都可以理解。
因此,我們使用函式
getUrls
來獲取所有的連結地址。
def getUrls():
url_init = ‘https://movie。douban。com/top250?start={0}&filter=’
urls = [url_init。format(index * 25) for index in range(10)]
return urls
但貌似這個列表頁面獲取不到我們所需的全部資訊,還需要去到具體電影的詳情頁才行。因此,我們可以先爬取列表頁,然後從列表頁獲取到詳情頁的連結地址,然後從詳情頁獲取我們所需的詳細資訊。
分析網頁
接下來我們需要確認一下我們需要的具體詳細資訊藏在哪個位置。開啟網址
https://movie。douban。com/top250?start=0&filter=
,然後開啟 chrome 的控制檯。
比如我們定位到「霸王別姬」。可以看到每一部電影都在一個單獨的 li 標籤內。在每個 li 裡面:
電影連結在
div。info > div。hd > a
裡面。
獲取到「霸王別姬」的詳情頁地址之後,我們再對該詳情頁進行分析。
我們發現,所有的電影資訊都在
這個標籤內的。
標題在 property=“v:itemreviewed” 的 span 裡面。
上映年份在 class=“year” 的 span 裡面。
導演在 class=“attrs” 的 span 裡面。
上映國家這個標籤比較特殊,沒有唯一性,所以可以使用正則表示式。
型別在 property=“v:genre” 的 span 裡面。
電影評分在 property=“v:average” 的 strong 裡面。
評價人數在 property=‘v:votes’ 的 span 裡面。
具體評分在 class_=‘ratings-on-weight’ 的 div 裡面。
嗯,很好,經過分析之後,我們知道了我們所需資訊的具體位置,接下來對這些內容進行抓取並解析即可。
獲取資料
抓取網頁資料需要用的
requests
庫,解析網頁需要用的
BeautifulSoup
庫,因此先將二者引我們的程式。
import bs4 as bs4
import requests
import re
因為獲取電影連結時需要解析網頁,獲取詳細資訊時同樣需要解析網頁,因此我們先定義一個名為
get_page_html(url)
的函式,用於從 url 獲取 html 內容。
同時,為了防止反爬蟲,我們需要定義一些 headers。
def get_page_html(url):
headers = {
‘Referer’: ‘https://movie。douban。com/chart’,
‘Host’: ‘movie。douban。com’,
‘User-Agent’: ‘Mozilla/5。0 (Macintosh; Intel Mac OS X 10_15_0) AppleWebKit/537。36 (KHTML, like Gecko) Chrome/79。0。3945。88 Safari/537。36’
}
try:
response = requests。get(url, headers=headers)
if response。status_code == 200:
return response。text
return None
except RequestException:
return None
接下來,我們開始獲取資料,需要一個解析電影詳情頁連結地址的函式。
def get_movie_url(html):
ans = []
soup = bs4。BeautifulSoup(html, ‘html。parser’)
items = soup。select(‘li > div。item’)
for item in items:
href = item。select(‘div。info > div。hd > a’)[0][‘href’]
ans。append(href)
return ans
在這個函式中,我們傳入整個頁面的 html 內容,該函式負責將電影詳情頁連結地址解析出來並以列表形式返回給呼叫方。
拿到了電影詳情頁的連結地址,最後我們只需要將詳細資訊解析出來即可。我們可以看到,詳情頁和列表頁有很多資訊都是重複的,因此我們可以從詳情頁獲取我們需要的所有資訊。
我們需要定義一個函式,用來解析詳情頁。
# 【名稱,連結。導演,國家,上映時間,型別,評分,[五星,四星佔比],評價人數】
def get_movie_info(url):
ans = {}
html = get_page_html(url)
soup = bs4。BeautifulSoup(html, ‘html。parser’)
content = soup。find(‘div’, id=‘content’)
## 作者
title = content。find(‘span’, property=‘v:itemreviewed’)。text
## 上映年份
year = content。find(‘span’, class_=‘year’)。text[1:5]
## 導演
directors = content。find(‘span’, class_=‘attrs’)。find_all(‘a’)
director = []
for i in range(len(directors)):
director。append(directors[i]。text)
## 上映國家/地區
country = content。find(text=re。compile(‘製片國家/地區’))。next_element
typeList = content。find_all(‘span’, property=‘v:genre’)
## 影片型別
type = []
for object in typeList:
type。append(object。text)
## 評分
average = content。find(‘strong’, property=‘v:average’)。text
## 評價人數
votes = content。find(‘span’, property=‘v:votes’)。text
## 具體評分(五星 四星人數佔比)
rating_per_items = content。find(‘div’, class_=‘ratings-on-weight’)。find_all(‘div’, class_=‘item’)
rating_per = [rating_per_items[0]。find(‘span’, class_=‘rating_per’)。text,
rating_per_items[1]。find(‘span’, class_=‘rating_per’)。text]
return {‘title’: title, ‘url’: url, ‘director’: director, ‘country’: country, ‘year’: year, ‘type’: type,
‘average’: average, ‘votes’: votes, ‘rating_per’: rating_per}
豆瓣的資料抓取難度不大,主要是要細心點分析頁面結構,將我們所需的資訊從錯綜複雜的網頁結構中找出來。因為我們所獲取的資訊比較多,所以這個函式稍微長了一點。
每一個欄位的資訊都是透過解析網頁原始碼獲得的,所以在準確度上來說是完全沒有問題的,同時,BeautifulSoup 的使用也簡單易上手,半小時左右就可以入門。關於 BeautifulSoup 的使用可以看 第65天:爬蟲利器 Beautiful Soup 之遍歷文件。
成功抓取到資料之後,我們還需要定義一個函式,用來將資料快取到資料庫或者本地檔案中,用於後續分析。這裡為了方便就直接寫入檔案了。
def writeToFile(content):
filename = ‘doubanTop250。txt’
with open(filename,‘a’) as f:
f。write(content + ‘\n’)
至此,我們的準備工作已經全部做完,就可以抓取資料了。
if __name__ == ‘__main__’:
list_urls = getUrls()
list_htmls = [get_page_html(url) for url in list_urls]
movie_urls = [get_movie_url(html) for html in list_htmls]
movie_details = [get_movie_info(url) for url in movie_urls[0]]
for detail in movie_details:
writeToFile(str(detail))
之後,就可以看的我們的資料了。大功告成。
總結
今天我們用
requests
庫和
BeautifulSoup
庫對豆瓣電影 top 250 進行了抓取,主要還是對
BeautifulSoup
庫的練習。本文思路清晰,只是分析網頁時需要多點耐心罷了,希望你也可以自己動手練習下,對於程式碼功底的提高有很大益處。
程式碼地址
示例程式碼:
https://
github。com/JustDoPython
/python-100-day/tree/master/day-119