python學習之抓取貓眼電影Top100榜單


近期開始學習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網絡爬蟲開發實戰》


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM