用Python爬取貓眼電影排行榜TOP100

參考資料《Python3網(wǎng)絡(luò)爬蟲開發(fā)實踐》,作者崔慶才

這篇博客參考了崔慶才的《Python3網(wǎng)絡(luò)爬蟲開發(fā)實踐》有關(guān)部分,記錄了爬取貓眼電影網(wǎng)排名前100的電影信息的過程。
主要步驟有:

  1. 訪問網(wǎng)站,獲取頁面源碼
  2. 解析頁面,得到想要的數(shù)據(jù)
  3. 循環(huán)爬取多個頁面
  4. 把數(shù)據(jù)寫入本地文件

1. 分析需要爬取的頁面結(jié)構(gòu)

訪問貓眼電影。觀察頁面,會看到首頁上有排名前十的電影信息。
找到頁面中的分頁,點擊不同的頁碼。對比不同頁面url的差別,會發(fā)現(xiàn)不同的分頁是以offset參數(shù)作為區(qū)分的。
因為每個頁面都顯示10條電影信息,所以offset是以10作為偏移量的。所以第1頁的offset=0,第2頁的offset=10,第3頁的offset=20,后面的頁面也是以此類推。

2. 抓取首頁

2.1 獲取首頁的源碼

首先定義一個方法,請求頁面,并獲得頁面源碼:

import requests


def get_one_page(url):
    headers = {
        'User-Agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_13_3) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/65.0.3325.162 Safari/537.36'
    }
    response = requests.get(url, headers=headers)
    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()

在打印結(jié)果中,可以看到頁面的源碼已經(jīng)返回。
獲取到的源碼中,有很多的信息不是我們需要的,這時候,需要把有用的信息提取出來。

2.2 使用正則提取信息

使用谷歌瀏覽器的開發(fā)者工具查看頁面的源代碼,可以發(fā)現(xiàn)我們需要的信息都包含在<dd>標(biāo)簽中。
排名信息包含在class為board-index的i標(biāo)簽中;
片名信息包含在class為name的p標(biāo)簽內(nèi)的a標(biāo)簽中;
主演姓名包含在class為star的p標(biāo)簽中;
上映日期包含在class為releasetime的p標(biāo)簽中;
評分分別包含在class為integerfraction的i標(biāo)簽中;
電影封面圖在class為board-img的img的src屬性中;
因此,可以寫一個正則表達(dá)式來提取一個電影的上述信息:

<dd>.*?board-index.*?>(\d+)</i>.*?data-src="(.*?)".*?name"><a.*?>(.*?)</a>.*?star">(.*?)</p>.*?releasetime">(.*?)</p>.*?integer">(.*?)</i>.*?fraction">(.*?)</i>.*?</dd>

把上面的正則表達(dá)式加入到代碼中:

import requests
import re

def get_one_page(url):
    headers = {
        'User-Agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_13_3) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/65.0.3325.162 Safari/537.36'
    }
    response = requests.get(url, headers=headers)
    if response.status_code == 200:
        return response.text
    return None


def parse_one_page(html):
    pattern = re.compile('<dd>.*?board-index.*?>(\d+)</i>.*?data-src="(.*?)".*?name"><a'
                         + '.*?>(.*?)</a>.*?star">(.*?)</p>.*?releasetime">(.*?)</p>'
                         + '.*?integer">(.*?)</i>.*?fraction">(.*?)</i>.*?</dd>', re.S)
    items = re.findall(pattern, html)
    print(items)


def main():
    url = 'http://maoyan.com/board/4'
    html = get_one_page(url)
    parse_one_page(html)


main()

輸出結(jié)果如下:


輸出結(jié)果截圖.png

可以看到,上面的輸出結(jié)果可讀性不是很好,把方法parse_one_page改進(jìn)如下:

def parse_one_page(html):
    pattern = re.compile('<dd>.*?board-index.*?>(\d+)</i>.*?data-src="(.*?)".*?name"><a'
                         + '.*?>(.*?)</a>.*?star">(.*?)</p>.*?releasetime">(.*?)</p>'
                         + '.*?integer">(.*?)</i>.*?fraction">(.*?)</i>.*?</dd>', re.S)
    items = re.findall(pattern, html)
    for item in items:
        yield {
            'index': item[0],
            'image': item[1],
            'title': item[2],
            'actor': item[3].strip()[3:],
            'time': item[4].strip()[5:],
            'score': item[5] + item[6]
        }

至此,單頁的電影信息已經(jīng)獲取完畢。
接著將獲取到的信息保存到文本文件中,以供后續(xù)的使用。

2.3 寫入文件

使用JSON庫的dumps()方法實現(xiàn)字典的序列化,并指定ensure_ascii參數(shù)為false,這樣可以保證輸出結(jié)果是中文形式,整理代碼如下:

import requests
import re
import json

def get_one_page(url):
    headers = {
        'User-Agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_13_3) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/65.0.3325.162 Safari/537.36'
    }
    response = requests.get(url, headers=headers)
    if response.status_code == 200:
        return response.text
    return None


def parse_one_page(html):
    pattern = re.compile('<dd>.*?board-index.*?>(\d+)</i>.*?data-src="(.*?)".*?name"><a'
                         + '.*?>(.*?)</a>.*?star">(.*?)</p>.*?releasetime">(.*?)</p>'
                         + '.*?integer">(.*?)</i>.*?fraction">(.*?)</i>.*?</dd>', re.S)
    items = re.findall(pattern, html)
    for item in items:
        yield {
            'index': item[0],
            'image': item[1],
            'title': item[2],
            'actor': item[3].strip()[3:],
            'time': item[4].strip()[5:],
            'score': item[5] + item[6]
        }


def write_to_file(content):
    with open('top100.txt', 'a', encoding='utf-8') as f:
        f.write(json.dumps(content, ensure_ascii=False)+'\n')


def main():
    url = 'http://maoyan.com/board/4'
    html = get_one_page(url)
    for item in parse_one_page(html):
        print(item)
        write_to_file(item)


main()

這時候就會發(fā)現(xiàn)本地多了一個名為top100.txt的文件,打開查看,里面存放了首頁排名前10的電影的各個信息。
接下來爬取另外頁面的電影信息。

3. 爬取其余頁面

爬取其余頁面,只需要對應(yīng)調(diào)整url的offset參數(shù)即可,改寫main方法如下:

def main(offset):
    url = 'http://maoyan.com/board/4?offset=' + str(offset)
    html = get_one_page(url)
    for item in parse_one_page(html):
        print(item)
        write_to_file(item)


if __name__ == '__main__':
    for i in range(10):
        main(offset=i*10)
        time.sleep(1)

為了防止過快請求頁面,被封,加入一個延時等待,最終代碼如下:

import json
import requests
from requests.exceptions import RequestException
import re
import time


def get_one_page(url):
    try:
        headers = {
            'User-Agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_13_3) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/65.0.3325.162 Safari/537.36'
        }
        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):
    pattern = re.compile('<dd>.*?board-index.*?>(\d+)</i>.*?data-src="(.*?)".*?name"><a'
                         + '.*?>(.*?)</a>.*?star">(.*?)</p>.*?releasetime">(.*?)</p>'
                         + '.*?integer">(.*?)</i>.*?fraction">(.*?)</i>.*?</dd>', re.S)
    items = re.findall(pattern, html)
    for item in items:
        yield {
            'index': item[0],
            'image': item[1],
            'title': item[2],
            'actor': item[3].strip()[3:],
            'time': item[4].strip()[5:],
            'score': item[5] + item[6]
        }


def write_to_file(content):
    with open('top100.txt', 'a', encoding='utf-8') as f:
        f.write(json.dumps(content, ensure_ascii=False) + '\n')


def main(offset):
    url = 'http://maoyan.com/board/4?offset=' + str(offset)
    html = get_one_page(url)
    for item in parse_one_page(html):
        print(item)
        write_to_file(item)


if __name__ == '__main__':
    for i in range(10):
        main(offset=i * 10)
        time.sleep(1)

查看top100.txt,會發(fā)現(xiàn)排名前100名的電影信息已經(jīng)整齊的寫入到了文件中。


完。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • Android 自定義View的各種姿勢1 Activity的顯示之ViewRootImpl詳解 Activity...
    passiontim閱讀 179,039評論 25 709
  • 文字/ 愚伯 攝影/秦申 篇一:北方的醪糟 對于米酒,我一向情有獨鐘,追其根源,可能...
    愚伯閱讀 881評論 3 2
  • 今天是離開家鄉(xiāng)的第一天,也是惡運開始的第一天,離開時沒有一個人來送我,但我并不失落,因為我媽暈車所以最好的還是不要...
    里小木閱讀 265評論 0 0

友情鏈接更多精彩內(nèi)容