近期開始學習python爬蟲,熟悉了基本庫、解析庫之后,決定做個小Demo來實踐下,檢驗學習成果。
1 本篇目標
- 抓取貓眼電影總排行榜Top100電影單
- 根據電影演員表統計演員上榜次數
2 url分析
目標站點為https://maoyan.com/board/4
,打開之后就可以看到排行榜信息,如圖所示
頁面上顯示10部電影,有名次、影片名稱、演員信息等信息。當拉到最下面點擊第二頁的時候,發現url變成了https://maoyan.com/board/4?offset=10
,對比原先多了個offset=10,第二頁是顯示排名11~20的電影,可以推斷這是一個偏移量,所以第一頁應該是offset=0,第二頁是offset=10,依次類推。
3 頁面抓取
url分析完之后,利用request模塊,我們就可以試試抓取頁面。
import requests
# 抓取一頁電影信息
def get_one_page(page_index):
url = 'https://maoyan.com/board/4?offset=' + str(page_index)
headers = {'User-Agent': 'Mozilla/5.0 (Windows NT 6.1; WOW64; rv:34.0) Gecko/20100101 Firefox/34.0'}
response = requests.get(url=url, headers=headers)
4 頁面分析
頁面成功抓取后需要解析提取信息,打開頁面的開發者模式,在Network監聽組件中查看源代碼(注意:不在Elements選項中直接查看源碼是因為該源碼可能經過javascirpt渲染),如圖:
由圖可知,一個影片所有信息是在一個<dd>標簽里面,一頁有10個。
其中名次信息位置是
<i class="board-index board-index-11">11</i>,
電影名稱信息位置是:
<p class="name">
<a href="/films/9025" title="喜劇之王" data-act="boarditem-click" data-val="{movieId:9025}">喜劇之王</a>
</p>
演員信息位置是:
<p class="star">主演:周星馳,莫文蔚,張柏芝</p>
知道了相關信息的位置,就可以利用Pyquery模塊對資源進行定位和抓取。繼續完善剛才的方法
import requests
from pyquery import PyQuery as pq
# 抓取一頁電影信息
def get_one_page(page_index):
url = 'https://maoyan.com/board/4?offset=' + str(page_index)
headers = {'User-Agent': 'Mozilla/5.0 (Windows NT 6.1; WOW64; rv:34.0) Gecko/20100101 Firefox/34.0'}
response = requests.get(url=url, headers=headers)
doc = pq(response.text)
page_info = ''
name_list = []
# 遍歷<dd>標簽,一頁抓取10部電影
for i in doc('dd').items():
# 計算空格,用於美化格式
name_len = len(i('.name').children().text())
other_len = 15 - name_len
space = ''
for j in range(other_len):
space += ' '
# 按照‘排序 電影名稱 主演’的方式返回文本
page_info += i('.board-index').text() + ' ' + i('.name').children().text() + space + i('.star').text() + '\n'
name_list += i('.star').text().split(':')[1].split(',')
# 返回一頁電影信息和演員信息
return page_info, name_list
5 代碼整合
在成功抓取一頁信息之后,整合代碼,將所有信息抓取並處理。
def info_handle():
# 存儲電影信息
movie_info = ''
# 存儲出現過的演員信息,有重復
name_info_list = []
for index in range(10):
movie_info += get_one_page(index * 10)[0]
name_info_list += get_one_page(index * 10)[1]
# 統計人名出現次數
name_count_list = []
for i in set(name_info_list):
dict_name_count = (i, name_info_list.count(i))
name_count_list.append(dict_name_count)
# 根據人名出現次數排行
name_count_list.sort(key=lambda k: k[1], reverse=True)
# 輸出電影信息到文本
with open('C:\\Users\\d\\Desktop\\xxx.txt', 'w') as f:
f.write(movie_info)
# 打印演員出現次數
for k, v in name_count_list:
print(k, v)
執行結果如下
txt文本內容:
控制台打印的排名如下:
從結果可以看出,100部電影,張國榮一人就占了7部,排名第一。
6 優化
從圖片可以看出,演員排名其實不是很直觀,最好是有一個圖表的方式。python的matplotlib模塊是一個數據可視化模塊,擁有很強的功能。不過目前我只是初步學習基礎模塊,並沒有深入了解matplotlib,所以只能從網上找到小demo,簡單了解用法之后加以改造。具體用法和原理,待后續深入學習。
聲明一個draw.py文件
import matplotlib.pyplot as plt
import numpy as np
class NameCount():
# 此函數用於垂直條形圖
def show_name_bard(self, name_list_sort, name_list_count):
plt.rcdefaults()
fig, ax = plt.subplots()
y_pos = np.arange(len(name_list_sort))
ax.barh(y_pos, name_list_count, align='center',
color='green', ecolor='black')
plt.rcParams['font.sans-serif'] = ['SimHei']
ax.set_yticks(y_pos)
ax.set_yticklabels(name_list_sort)
ax.invert_yaxis() # labels read top-to-bottom
# ax.set_xlabel('')
ax.set_title('Top100電影演員占有部數統計')
# 在圖畫上顯示數字
for x, y in enumerate(name_list_count):
plt.text(y, x + 0.1, '%s' % y)
plt.show()
def getNameTimesSort(self, name_list):
name_list.sort(key=lambda k: k[1], reverse=True)
# 按出現次數排序后的人名列表
name_list_sort = []
# 按出現次數排序后的人名次數列表,取前20名
name_list_count = []
for k, v in name_list[0:20]:
name_list_sort.append(k)
name_list_count.append(v)
# 繪制條形圖
self.show_name_bard(name_list_sort, name_list_count)
然后在info_handle方法中引入getNameTimesSort方法,講原先用於打印的排好序的name_count_list傳入
# 畫出垂直條形圖
statistics = draw.NameCount()
statistics.getNameTimesSort(name_count_list)
這樣就可以生成圖像,一目了然:
參考:
《python3網絡爬蟲開發實戰》