1. 程式人生 > >python爬蟲系列(1):使用python3和正則表示式獲取貓眼電影排行榜資料

python爬蟲系列(1):使用python3和正則表示式獲取貓眼電影排行榜資料

簡述

這次打算寫一個爬蟲系列,一邊也想好好總結鞏固學習的知識,一邊做總結筆記,方便以後回憶。這次我們使用Python3正則表示式來爬取一個簡單html頁面資訊,就從貓眼電影的排行榜單開始吧。如果讀到這篇文章的是位大神,期望您能不吝賜教,指正錯誤,如果您是小白,咋們可以一同探討學習,共同進步。下面咋們開始.....

分析

首先使用瀏覽器登入到貓眼電影頁面,點選上面的“榜單”字樣,下面可以看到“熱映口碑榜”、“最受期待榜”、“國內票房榜”、“北美票房榜”和“Top100榜”。這次我們把這些個排行榜全部都爬取下來,並且根據自己的選擇,期望顯示獲得哪個排行榜,開始動刀子,第一步當然是開啟瀏覽器的開發者工具,按F5重新整理一遍,可以看到下圖:

看到右邊的preview就是整個頁面的html主體資料,主要分析一下這個頁面的html結構,將我們需要的資訊提取出來即可,我們往下翻,可以看到資訊如下

最上面那些個各種“榜”正是我們需要的榜單,這時候在觀察分析一下這些個“榜”節點的情況:   

<a data-act="subnav-click" data-val="{subnavClick:1}" href="/board/1">國內票房榜</a>

再對應著點選每一個榜單檢視其相應的url,可以發現:

可以知道,每個榜單的url都是最後的那個數字不同,對應相應的榜單。這個數字正好就是上面提到的a節點中的data-val這個屬性後的那個數字,或者是href中的“/board/1”,這樣就得到了我們第一部分所需的資料,即每一個榜單 ,現在就是想辦法將數字提取出來就可以了,這時候就是正則表示式上場的時候了:

這裡獲取的是a節點中的data-val數字,當然也可以獲取href屬性,使用的正則表示式為:

<a d.*?subnavClick:(\d).*?>(.*?)</a>

這樣就將榜單的名字和數字都一一對應的爬取下來了,相應的程式碼為:

#獲取當前可以檢視哪些排行榜
def getAllTopList(url):
    NO = 1
    response = requests.get(url, headers = header)
    if response.status_code == 200:
        allTop = re.findall('<a d.*?subnavClick:(\d).*?>(.*?)</a>' ,response.text, re.S)
    for movie in allTop:
        print('NO.' + str(NO) + ' ' + movie[1])
        NO += 1
    return allTop

榜單列表有了,這時候就需要將該頁面現有的排行榜資訊爬取下來,在preview中可以看到電影的資訊放在<dd></dd>節點中,我們就直接查詢dd節點中的資料,可以看到電影名字在title屬性中:

<a href="/films/1200486" title="我不是藥神" class="image-link" data-act="boarditem-click" data-val="{movieId:1200486}">

這時候可以再編輯一個函式用於獲取當前頁面的所有電影名字和排序:

#獲取一個頁面的資訊
def getOnePage(url):
    response = requests.get(url, headers=header)
    if response.status_code == 200:
        allTop = re.findall('<dd>.*?board-index-(\d+).*?title="(.*?)".*?/p>.*?</dd>', response.text, re.S)
    return allTop,response.text

有些榜單一頁資訊放不下,這時候就需要判斷當前頁面是否有第二頁並且請求下一頁的頁面,獲取資料:

#判斷是否有,並返回下一頁的頁碼
def judgeNextPage(text):
    result = re.search('style="cursor: default".*?<li>[ ]+<a class="page_(\d+)".*?"(\?offset=\d+)".*?下一頁</a>', text, re.S)
    if result == None:
        return None
    else:
        return (result.group(1),result.group(2))

#根據選擇的顯示出相應的排行榜
def showTopList(url, urlNum):
    newUrl = url + '/' + urlNum[0]
    response = requests.get(newUrl, headers=header)
    TOPINFO,htmlText = getOnePage(newUrl)
    pageInfo = judgeNextPage(htmlText)
    while pageInfo != None:
        nextPageUrl = newUrl + pageInfo[1]
        topInfo,htmlText = getOnePage(nextPageUrl)
        TOPINFO += topInfo
        pageInfo = judgeNextPage(htmlText)
    for x in TOPINFO:
        print(x[0] + ':' + x[1])

編碼

這裡是所有的程式碼,一眼看上去都是正則表示式:

import re
import requests
import time

topURL = 'https://maoyan.com/board'
header = {
    'User-Agent': 'Mozilla / 5.0(Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/55.0.2883.87 Safari/537.36'
}

#獲取當前可以檢視哪些排行榜
def getAllTopList(url):
    NO = 1
    response = requests.get(url, headers = header)
    if response.status_code == 200:
        allTop = re.findall('<a d.*?subnavClick:(\d).*?>(.*?)</a>' ,response.text, re.S)
    for movie in allTop:
        print('NO.' + str(NO) + ' ' + movie[1])
        NO += 1
    return allTop

#獲取一個頁面的資訊
def getOnePage(url):
    response = requests.get(url, headers=header)
    if response.status_code == 200:
        allTop = re.findall('<dd>.*?board-index-(\d+).*?title="(.*?)".*?/p>.*?</dd>', response.text, re.S)
    return allTop,response.text

#判斷是否有,並返回下一頁的頁碼
def judgeNextPage(text):
    result = re.search('style="cursor: default".*?<li>[ ]+<a class="page_(\d+)".*?"(\?offset=\d+)".*?下一頁</a>', text, re.S)
    if result == None:
        return None
    else:
        return (result.group(1),result.group(2))

#根據選擇的顯示出相應的排行榜
def showTopList(url, urlNum):
    newUrl = url + '/' + urlNum[0]
    response = requests.get(newUrl, headers=header)
    TOPINFO,htmlText = getOnePage(newUrl)
    pageInfo = judgeNextPage(htmlText)
    while pageInfo != None:
        nextPageUrl = newUrl + pageInfo[1]
        topInfo,htmlText = getOnePage(nextPageUrl)
        TOPINFO += topInfo
        pageInfo = judgeNextPage(htmlText)
    for x in TOPINFO:
        print(x[0] + ':' + x[1])

if __name__ == '__main__':
    while True:
        topList = getAllTopList(topURL)
        select = int(input('選擇期望檢視的排行榜:'))
        if select <= len(topList):
            showTopList(topURL, topList[select - 1])
        print('-------------------------------------')

執行