貓眼電影榜爬蟲實例

目錄

一、前言:

二、源碼:

三、爬取結果doc文本展示:

四、關鍵庫:

五、主要的優化點:

六、最終耗時

七、寫到最後


一、前言:

本代碼參考網上現有爬取貓眼排行榜代碼進行優化及修改並新增寫入doc,內容排序,圖片爬取等功能,因參考鏈接後來沒有找到,在這裏對原作者說聲抱歉。

環境爲python3,編譯器使用pycharm。

話不多說,直接帖代碼。

二、源碼:

import time
import json
import requests
import socket
from pyquery import PyQuery
from multiprocessing import Pool
from requests.exceptions import RequestException
from urllib.request import urlretrieve
from src.File import File
from retrying import retry
from docx import Document
from docx.shared import Inches


def get_one_page(url):
    # 獲取一個頁面
    headers = {"User-Agent": "Mozilla/5.0"}
    try:
        response = requests.get(url, headers=headers)
        if response.status_code != 200:
            return None
    except RequestException:
        return None

    return response.text


@retry(stop_max_attempt_number=4)
def save_img(img, name):
    for img_info in img("img").items():
        img_test = PyQuery(img_info)
        try:
            if img_test("img").attr("data-src") is not None:
                url = img_test("img").attr("data-src")
                img_name = "picture/" + name + ".png"
                if file.isFileExit(img_name) is False:
                    urlretrieve(url, img_name)
        except:
            raise Exception(name + " picture is not install")


def pase_one_page(text):
    # 解析頁面內容
    doc = PyQuery(text)
    for info in doc("dl.board-wrapper dd").items():
        dct = {}
        dct["index"] = info.find(".board-index").text()
        dct["name"] = info.find("p.name a").text()
        dct["star"] = info.find("p.star").text()
        dct["releasetime"] = info.find("p.releasetime").text()
        dct["score"] = info.find(".score").text()
        img = PyQuery(info)

        try:
            save_img(img, dct["name"])
        except:
            print(dct["name"] + " picture is not install")

        yield dct


def write_to_file(content):
    # 寫入文件
    with open("movie.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={offset}"
    text = get_one_page(url.format(offset=offset))
    for item in pase_one_page(text):
        write_to_file(item)


def compare(every):
    j = json.loads(every)
    return int(j["index"])


def sort_file():
    lines = []
    f = open("movie.txt", "r")
    for line in f:
        lines.append(line)
    f.close()
    if len(lines) is not 0:
        lines.sort(key=compare)
        f = open("movie.txt", "w+")
        for line in lines:
            f.write(line)
        f.close()


def write_to_doc():
    doc = Document()

    lines = []
    f = open("movie.txt", "r")
    for line in f:
        lines.append(line)
        j = json.loads(line)
        img = "picture/" + str(j["name"]) + ".png"
        doc.add_paragraph(j["index"] + "、" + j["name"])
        doc.add_picture(img, width=Inches(2))
        doc.add_paragraph(j["star"])
        doc.add_paragraph(j["releasetime"])
        doc.add_paragraph("評分: " + str(j["score"]))
        doc.add_paragraph("-" * 118)
        doc.save("movie.doc")


def init():
    socket.setdefaulttimeout(2)
    file.remove_file("picture")
    with open("movie.txt", "r+") as f:
        f.truncate()


if __name__ == "__main__":
    start = time.time()

    file = File()

    if file.isDir("picture") is False:
        file.mkdir("picture")

    init()
    pool = Pool(processes=10)
    pool.map(main, [i * 10 for i in range(10)])
    pool.close()
    sort_file()

    write_to_doc()

    end = time.time()
    print("time is " + str(end - start) + "s")

三、爬取結果doc文本展示:

四、關鍵庫:

1、pyquery

解析html庫,用於將請求到的html網站源碼進行逐段標籤的解析,提取有用的榜單信息,過濾不需要的信息。

2、multiprocessing

線程池,用於開啓線程池,對線程進行管理,對資源進行方便管理。

3、requests

用於實現http請求,該庫封裝了很多方便的api,簡化http的寫法。

4、urllib3

主要使用了urlretrieve,用於請求服務器的圖片資源,並保存到本地。

5、retrying

python提供的重試包,通過註解的方式來對某一可能運行失敗的程序段進行重試功能。

6、docx

python提供的用於操作doc文檔的庫,利用該庫可以方便的將文字和圖片按照一定的順序方式寫入doc文檔中。

五、主要的優化點:

1、多線程的優化,排榜爲100部電影,分爲10個線程去爬取,單個線程處理10部電影,限制線程池數量爲10,經過測試在這個時候運行速度最快。

2、爬取內容的優化,增加對電影海報圖片的爬取,並利用urlretrieve進行下載保存到本地,因該部分需要請求服務器圖片資源,可能導致失敗,利用retrying模塊對該部分功能進行重試4次的操作,保證圖片下載完全。

3、保存文件txt的優化,txt不支持對於圖片的保存,且多線程下對文件進行操作時會導致電影排榜的亂序,所以經過思考,該用doc格式來進行結果的保存,並對爬好的數據進行重新遍歷排序,並對doc文本中的內容進行美化。

4、對文件目錄進行結構優化,並在每次執行前對文本進行清空操作,避免影響下一次的結果保存。

5、對爬取速度進行優化,經過實驗,發現在增加圖片的爬取功能後,爬蟲運行速度會大幅降低,原因在於訪問圖片資源的失敗時過於耗時,所以對requests進行了進一步的瞭解,發現該庫的底層實現依舊採用的是socket,所以通過對socket的默認超時時間設置爲2s,來加快整個爬取的速度。同時當圖片文件存在時,跳過對該圖片的資源請求,以節省時間。

六、最終耗時

七、寫到最後

1、此代碼中有引入我其它的封裝好的一些文件操作類,可能無法直接使用,這些都是比較基礎的文件操作,想必修改起來並不困難。

2、這份代碼並非沒有優化點,還是有很多值得優化思考的地方,包括界面的加入以及定時爬取的功能,常駐工具的設置,路徑的變化等等,如何進一步優化完善就各憑本事吧,我也只是做了部分。

3、有個缺陷在於如果爬取到的圖片數量依然不足100,在寫入doc文本時會有異常,這個加一個計數判斷就好,我這裏就懶得弄了,直接retrying次數增加也是可以的。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章