爬取目標
本文將提取貓眼電影 TOP100 排行榜的電影名稱、時間、評分、圖片等信息,URL 爲http://maoyan.com/board/4,提取的結果我們以 excel 格式保存下來。
準備工作
保證電腦安裝了 python3.6 和已經安裝好了 requests 庫、beautifulsoup 庫和 openpyxl 庫。
前期安裝步驟可以參考:https://germey.gitbooks.io/python3webspider/1-%E5%BC%80%E5%8F%91%E7%8E%AF%E5%A2%83%E9%85%8D%E7%BD%AE.html
爬取分析
打開http://maoyan.com/board/4我們會發現榜單主要顯示 4 個數據:電影名、主演、上映時間和評分。
如圖所示:
網頁下滑到最下方可以發現有分頁的列表,我們點擊一下第二頁會發現頁面的 URL 變成了http://maoyan.com/board/4?offset=10,比之前的頁面多了一個 offset=10 的參數,而且頁面顯示的是排行 11-20 名的電影。
由此我們可以總結出規律,offset 代表了一個偏移量值,如果偏移量爲 n,則顯示的電影序號就是 n+1 到 n+10,每頁顯示 10 個。所以我們如果想獲取 TOP100 電影,只需要分開請求 10 次,而 10 次的 offset 參數設置爲 0,10,20,…,90 即可,這樣我們獲取不同的頁面結果之後再用正則表達式提取出相關信息就可以得到 TOP100 的所有電影信息了。
抓取首頁
import requests
def get_one_page(url):
response = requests.get(url)
if response.status_code == 200:
return response.text
return None
def main():
url = 'http://maoyan.com/board/4'
html = get_one_page(url)
print(html)
main()
這樣我們就可以獲取首頁的源代碼了,獲取源代碼之後我們要對頁面進行解析,提取出我們想要的信息。
使用 BeautifulSoup 進行提取
接下來我們回到網頁看一下頁面的真實源碼,在開發者工具中 Network 監聽(建議使用谷歌瀏覽器,按 F12 即可查看網頁信息),然後查看一下源代碼。如圖所示:
注意這裏不要在 Elements 選項卡直接查看源碼,此處的源碼可能經過 JavaScript 的操作而和原始請求的不同,我們需要從Network選項卡部分查看原始請求得到的源碼。
查看其中的一條源代碼如圖所示:
可以看到電影名、主演、上映時間和評分分別在屬性 class=”name”、class=”star”、class=”release” 和 class=”score”的文本中
那麼我們可以用 BeautifulSoup 的方法進行提取:
def parse_one_page(html):
soup = bs4.BeautifulSoup(html, 'lxml')
# 獲取電影名
movies = []
targets = soup.find_all(class_='name')
for each in targets:
movies.append(each.get_text())
# 獲取評分
scores = []
targets = soup.find_all(class_='score')
for each in targets:
scores.append(each.get_text())
# 獲取主演信息
star_message = []
targets = soup.find_all(class_='star')
for each in targets:
star_message.append(each.get_text().split('\n')[1].strip())
print(each.get_text().split('\n')[1].strip())
# 獲取上映時間
play_time = []
targets = soup.find_all(class_='releasetime')
for each in targets:
play_time.append(each.get_text())
result = []
length = len(movies)
for j in range(length):
result.append([movies[j], scores[j], star_message[j], play_time[j]])
return result
這樣我們就成功的將一頁的 10 個電影信息都提取出來了
寫入文件
隨後我們將提取的結果做成 excel 表格形式
def save_to_excel(result):
wb = openpyxl.Workbook()
ws = wb.active
ws['A1'] = '電影名稱'
ws['B1'] = '評分'
ws['C1'] = '主演'
ws['D1'] = '上映時間'
for item in result:
ws.append(item)
wb.save('貓眼電影TOP100.xlsx')
分頁爬取
但我們需要爬取的數據是 TOP100 的電影,所以我們還需要遍歷一下給這個鏈接傳入一個 offset 參數,實現其他 90 部電影的爬取
for i in range(10):
headers = {
'User-Agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_11_4) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/53.0.2785.116 Safari/537.36',
}
url = 'http://maoyan.com/board/4?offset=' + str(i * 10)
html = get_one_page(url, headers)
result.extend(parse_one_page(html))
整合代碼
到此爲止,我們的貓眼電影 TOP100 的爬蟲就全部完成了,再稍微整理一下,完整的代碼如下:
import requests
import bs4
from requests.exceptions import RequestException
import openpyxl
def get_one_page(url, headers):
try:
response = requests.get(url, headers=headers)
if response.status_code == 200:
return response.text
return None
except RequestException:
return None
def parse_one_page(html):
soup = bs4.BeautifulSoup(html, 'lxml')
# 獲取電影名
movies = []
targets = soup.find_all(class_='name')
for each in targets:
movies.append(each.get_text())
# 獲取評分
scores = []
targets = soup.find_all(class_='score')
for each in targets:
scores.append(each.get_text())
# 獲取主演信息
star_message = []
targets = soup.find_all(class_='star')
for each in targets:
star_message.append(each.get_text().split('\n')[1].strip())
print(each.get_text().split('\n')[1].strip())
# 獲取上映時間
play_time = []
targets = soup.find_all(class_='releasetime')
for each in targets:
play_time.append(each.get_text())
result = []
length = len(movies)
for j in range(length):
result.append([movies[j], scores[j], star_message[j], play_time[j]])
return result
def save_to_excel(result):
wb = openpyxl.Workbook()
ws = wb.active
ws['A1'] = '電影名稱'
ws['B1'] = '評分'
ws['C1'] = '主演'
ws['D1'] = '上映時間'
for item in result:
ws.append(item)
wb.save('貓眼電影TOP100.xlsx')
def main():
result = []
for i in range(10):
headers = {
'User-Agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_11_4) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/53.0.2785.116 Safari/537.36',
}
url = 'http://maoyan.com/board/4?offset=' + str(i * 10)
html = get_one_page(url, headers)
result.extend(parse_one_page(html))
save_to_excel(result)
if __name__ == '__main__':
main()
運行結果如下圖:
結語
本文參考崔慶才的《Python3 網絡爬蟲開發實戰》代碼部分將正則表達式解析換成 BeautifulSoup 解析。
本代碼還有改進的地方,比如解析代碼時有些代碼重複了,使用的單進程爬取速度較慢,最近 requests 的作者新開發了一個庫 request-html,集網頁獲取與解析與一體,使爬取更簡單。有興趣的可以看看官方文檔傳送門。希望大家多多交流。