1. 程式人生 > >Python爬蟲之一:抓取貓眼電影TOP100

Python爬蟲之一:抓取貓眼電影TOP100

執行平臺: Windows
Python版本: Python3.6
IDE: Sublime Text
其他工具: Chrome瀏覽器

1. 抓取單頁內容

瀏覽器開啟貓眼電影首頁,點選“榜單”,然後再點選”TOP100榜”,就能看到想要的了。

1貓眼電影榜單頁

接下來通過程式碼來獲取網頁的HTML程式碼。

# 如果電腦裡沒有安裝requests,使用:pip install requests 進行安裝
import requests
from requests.exceptions import RequestException

def get_one_page(url):
    '''
    獲取網頁html內容並返回
    '''
try: # 獲取網頁html內容 response = requests.get(url) # 通過狀態碼判斷是否獲取成功 if response.status_code == 200: return response.text return None except RequestException: return None def main(): url = 'http://maoyan.com/board/4' html = get_one_page(url) print(html) if
__name__ == '__main__': main()
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25

執行結果如下:

2抓取內容截圖

2. 正則表示式提取有用資訊

在上圖中,已經標註出我們將要提取的內容,下面用程式碼實現:

import re

def parse_one_page(html):
    '''
    解析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] } # 修改main()函式 def main(): url = 'http://maoyan.com/board/4' html = get_one_page(url) for item in parse_one_page(html): print(item)
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29

執行結果如下:

3獲取網頁資訊結果

3. 儲存資訊

獲取電影資訊之後,要儲存起來留用。要儲存的有文字資訊和電影封面。

import os

def write_to_file(content):
    '''
    將文字資訊寫入檔案
    '''
    with open('result.txt', 'a', encoding='utf-8') as f:
        f.write(json.dumps(content, ensure_ascii=False) + '\n')
        f.close()

def save_image_file(url, path):
    '''
    儲存電影封面
    '''
    ir = requests.get(url)
    if ir.status_code == 200:
        with open(path, 'wb') as f:
            f.write(ir.content)
            f.close()

# 修改main()函式
def main():
    url = 'http://maoyan.com/board/4'
    html = get_one_page(url)
    # 封面資料夾不存在則建立
    if not os.path.exists('covers'):
        os.mkdir('covers')

    for item in parse_one_page(html):
        print(item)
        write_to_file(item)
        save_image_file(item['image'], 'covers/' + '%03d'%int(item['index']) + item['title'] + '.jpg')
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32

下面為儲存結果:

4文字儲存結果

5封面儲存結果

4.下載TOP100所有電影資訊

通過點選標籤頁發現只是URL變化了:

6不同頁面點選效果

修改main函式以動態改變URL:

def main(offset):
    url = 'http://maoyan.com/board/4?offset=' + str(offset)
    html = get_one_page(url)
    # 封面資料夾不存在則建立
    if not os.path.exists('covers'):
        os.mkdir('covers')

    for item in parse_one_page(html):
        print(item)
        write_to_file(item)
        save_image_file(item['image'], 'covers/' + '%03d'%int(item['index']) + item['title'] + '.jpg')

if __name__ == '__main__':
    for i in rang(10):
        main(i * 10)
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15

到此我們已經將TOP100的電影資訊和封面全部得到了。

5.多執行緒抓取

此次抓取的資料不算多,但是為了學習,使用多程序進行抓取,以應對以後大量的資料抓取。

from multiprocessing import Pool

if __name__ == '__main__':
    pool = Pool()
    pool.map(main, [i*10 for i in range(10)])
  • 1
  • 2
  • 3
  • 4
  • 5

下面為普通抓取和多程序抓取的時間對比:

7多程序速度對比

以下為完整程式碼:

#-*- coding: utf-8 -*-
import re
import os
import json
import requests
from multiprocessing import Pool
from requests.exceptions import RequestException

def get_one_page(url):
    '''
    獲取網頁html內容並返回
    '''
    try:
        # 獲取網頁html內容
        response = requests.get(url)
        # 通過狀態碼判斷是否獲取成功
        if response.status_code == 200:
            return response.text
        return None
    except RequestException:
        return None

def parse_one_page(html):
    '''
    解析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('result.txt', 'a', encoding='utf-8') as f:
        f.write(json.dumps(content, ensure_ascii=False) + '\n')
        f.close()

def save_image_file(url, path):
    '''
    儲存電影封面
    '''
    ir = requests.get(url)
    if ir.status_code == 200:
        with open(path, 'wb') as f:
            f.write(ir.content)
            f.close()

def main(offset):
    url = 'http://maoyan.com/board/4?offset=' + str(offset)
    html = get_one_page(url)
    # 封面資料夾不存在則建立
    if not os.path.exists('covers'):
        os.mkdir('covers')

    for item in parse_one_page(html):
        print(item)
        write_to_file(item)
        save_image_file(item['image'], 'covers/' + '%03d'%int(item['index']) + item['title'] + '.jpg')

if __name__ == '__main__':
    # 使用多程序提高效率
    pool = Pool()
    pool.map(main, [i*10 for i in range(10)])