聲明:本部落格隻是簡單的爬蟲示範,并不涉及任何商業用途。
前言
為什麼選取豆瓣電影Top 250來進行爬取呢?原因是它的網頁結構相當規整,比較适合爬蟲新手練習。下面我将詳細展示爬蟲的整個過程。
爬蟲過程
網頁連結分析
爬蟲起點網頁為豆瓣電影 Top 250,整個250部電影一共分10頁,每頁對應的連結如下:
https://movie.douban.com/top250?start=0&filter=
https://movie.douban.com/top250?start=25&filter=
https://movie.douban.com/top250?start=50&filter=
https://movie.douban.com/top250?start=75&filter=
...
https://movie.douban.com/top250?start=225&filter=
上述連結的結構都一緻,唯一的差別是在查詢字元串
start = number
的位置,是以,要想爬取網站的10頁,可以用一個變量page來進行疊代。
請求網頁
請求網頁我使用的是requests庫,最開始我試探性的直接使用get函數請求網頁内容,請求代碼如下:
import requests
url = 'https://movie.douban.com/top250?start=0&filter='
reponse = requests.get(url)
print(reponse.status_code)
#418
結果伺服器響應的代碼是418,說明請求未成功,于是我又将User-Agent傳遞給了get函數的headers參數,結果傳回200,說明請求成功,實驗代碼為:
import requests
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/81.0.4044.129 Safari/537.36'}
reponse = requests.get(url,headers = headers)
print(reponse.status_code)
#200
若讀者想要複現代碼,需要擷取浏覽器的User-Agent參數,對于Chrome浏覽器,可以直接在浏覽器中輸入
about:version
,會出現如下界面:
從其中就可以擷取到User-Agent參數。在這些都搞定了以後,爬蟲程式的請求部分就已經基本上完成了,下面是完整的請求代碼:
def HTMLDownloader(page):
url = 'https://movie.douban.com/top250?start='+ str(page*25) +'&filter='
#print(url)
headers = {'User-Agent':'Mozilla/5.0 (Windows NT 10.0; Win64; x64) \
AppleWebKit/537.36 (KHTML, like Gecko) Chrome/81.0.4044.129 Safari/537.36'}
try:
reponse = requests.get(url,headers = headers)
if reponse.status_code == 200:#響應成功
return reponse.text
except requests.RequestException as e:
return None
解析網頁
對于網頁的解析使用的是BeautifulSoup,我準備爬取的各部電影的資料有:
- 電影名
- 豆瓣評分
- 電影簡介
- 電影評論
以Top 250的第一頁為例,該網頁部分内容如下:
右鍵檢視其網頁源碼,如下圖:
從網頁源碼中我們可以發現網頁中的每部電影的資訊都在一個具有屬性為
class = "item"
的div标簽中,利用這個,我們可以使用find_all()函數來擷取網頁中包含所有電影的div标簽。
對于每部電影我們要爬取的屬性可以通過如下方式擷取:
- 從包含屬性
的span标簽中可以擷取電影名;class = "title"
- 從包含屬性
的span标簽中可以擷取電影的豆瓣評分;class = "rating_num"
- 從包含屬性
的p标簽,我們可以擷取電影的簡介,其中包括了導演,主演,電影年份等資訊。class = ''
- 從包含屬性
的span标簽,我們可以擷取電影的評論。class = 'inq'
通過上述分析内容,網頁分析函數的雛形就基本上出來了,完整的分析程式為:
def HTMLParser(reponse):
"""
網頁解析出的電影資料都儲存在清單中
清單的每個元素都包含一部電影的資訊
"""
outcome = []
if reponse == None:
pass
else:
soup = BeautifulSoup(reponse,'lxml') #BeautifulSoup構造方法
#尋找所有電影的div标簽
items = soup.findAll('div',attrs={'class':'item'})
#從div标簽中擷取電影的各種資訊
for item in items:
title = item.find('span',attrs = {'class':'title'}).string
rank = item.find('span',attrs = {'class':'rating_num'}).string
movinfo = item.find('p',attrs = {'class':''}).text
#有的電影沒有評論
if item.find('span',attrs = {'class':'inq'}):
comment = item.find('span',attrs = {'class':'inq'}).string
else:
comment = ''
print('crawing',title,rank,movinfo,comment)
outcome.append([title,rank,movinfo.strip(),comment.strip()])
return outcome
儲存提取的資訊
爬取完整250部電影的資訊後,我将其儲存在excel中,下面是儲存程式:
def MovieInfoSaver(mov):
workbook = openpyxl.Workbook() #openpyxl子產品需要自己安裝
sheet = workbook.active
sheet.title = 'douban_movie'
sheet.cell(1,1,'電影名')
sheet.cell(1,2,'豆瓣評分')
sheet.cell(1,3,'簡介')
sheet.cell(1,4,'評論')
for idx,m in enumerate(mov):
sheet.cell(idx + 2,1,m[0])
sheet.cell(idx + 2,2,m[1])
sheet.cell(idx + 2,3,m[2])
sheet.cell(idx + 2,4,m[3])
workbook.save(u'douban_hrank_movie.xlsx') # 儲存工作簿
完整爬蟲程式
最後給出完整的爬蟲程式
from bs4 import BeautifulSoup
import requests
import openpyxl
def HTMLDownloader(page):
url = 'https://movie.douban.com/top250?start='+ str(page*25) +'&filter='
#print(url)
headers = {'User-Agent':'Mozilla/5.0 (Windows NT 10.0; Win64; x64) \
AppleWebKit/537.36 (KHTML, like Gecko) Chrome/81.0.4044.129 Safari/537.36'}
try:
reponse = requests.get(url,headers = headers)
if reponse.status_code == 200:#響應成功
return reponse.text
except requests.RequestException as e:
return None
def HTMLParser(reponse):
"""
網頁解析出的電影資料都儲存在清單中
清單的每個元素都包含一部電影的資訊
"""
outcome = []
if reponse == None:
pass
else:
soup = BeautifulSoup(reponse,'lxml') #BeautifulSoup構造方法
#尋找所有電影的div标簽
items = soup.findAll('div',attrs={'class':'item'})
#從div标簽中擷取電影的各種資訊
for item in items:
title = item.find('span',attrs = {'class':'title'}).string
rank = item.find('span',attrs = {'class':'rating_num'}).string
movinfo = item.find('p',attrs = {'class':''}).text
#有的電影沒有評論
if item.find('span',attrs = {'class':'inq'}):
comment = item.find('span',attrs = {'class':'inq'}).string
else:
comment = ''
print('clawing',title,rank,movinfo,comment)
outcome.append([title,rank,movinfo.strip(),comment.strip()])
return outcome
def MovieInfoSaver(mov):
"""
儲存爬蟲結果到excel中
"""
workbook = openpyxl.Workbook()
sheet = workbook.active
sheet.title = 'douban_movie'
sheet.cell(1,1,'電影名')
sheet.cell(1,2,'豆瓣評分')
sheet.cell(1,3,'簡介')
sheet.cell(1,4,'評論')
for idx,m in enumerate(mov):
sheet.cell(idx + 2,1,m[0])
sheet.cell(idx + 2,2,m[1])
sheet.cell(idx + 2,3,m[2])
sheet.cell(idx + 2,4,m[3])
workbook.save(u'douban_hrank_movie.xlsx') # 儲存工作簿
if __name__ == "__main__":
movinfo = []
#通過page變量請求10個頁面
for page in range(10):
reponse = HTMLDownloader(page)
movinfo += HTMLParser(reponse)
MovieInfoSaver(movinfo)