1. 程式人生 > >Python爬蟲之多線程下載豆瓣Top250電影圖片

Python爬蟲之多線程下載豆瓣Top250電影圖片

process current ocs code roc 輸出 wait div 允許

爬蟲項目介紹

??本次爬蟲項目將爬取豆瓣Top250電影的圖片,其網址為:https://movie.douban.com/top250, 具體頁面如下圖所示:

技術分享圖片

??本次爬蟲項目將分別不使用多線程和使用多線程來完成,通過兩者的對比,顯示出多線程在爬蟲項目中的巨大優勢。本文所使用的多線程用到了concurrent.futures模塊,該模塊是Python中最廣為使用的並發庫,它可以非常方便地將任務並行化。在concurrent.futures模塊中,共有兩種並發模塊,分別如下:

  • 多線程模式:ThreadPoolExecutor,適合 IO密集型任務;
  • 多進程模式:ProcessPoolExecutor,適合計算密集型任務。

具體的關於該模塊的介紹可以參考其官方網址:https://docs.python.org/3/library/concurrent.futures.html 。
??本次爬蟲項目將會用到concurrent.futures模塊中的ThreadPoolExecutor類,多線程豆瓣Top250電影圖片。下面將會給出本次爬蟲項目分別不使用多線程和使用多線程的對比,以此來展示多線程在爬蟲中的巨大優勢。

不使用多線程

??首先,我們不使用多線程來下載豆瓣Top250電影圖片,其完整的Python代碼如下:

import time
import requests
import urllib.request
from bs4 import BeautifulSoup

# 該函數用於下載圖片
# 傳入函數: 網頁的網址url
def download_picture(url):

    # 獲取網頁的源代碼
    r = requests.get(url)
    # 利用BeautifulSoup將獲取到的文本解析成HTML
    soup = BeautifulSoup(r.text, "lxml")
    # 獲取網頁中的電影圖片
    content = soup.find(‘div‘, class_=‘article‘)
    images = content.find_all(‘img‘)
    # 獲取電影圖片的名稱和下載地址
    picture_name_list = [image[‘alt‘] for image in images]
    picture_link_list = [image[‘src‘] for image in images]

    # 利用urllib.request..urlretrieve正式下載圖片
    for picture_name, picture_link in zip(picture_name_list, picture_link_list):
        urllib.request.urlretrieve(picture_link, ‘E://douban/%s.jpg‘ % picture_name)


def main():

    # 全部10個網頁
    start_urls = ["https://movie.douban.com/top250"]
    for i in range(1, 10):
        start_urls.append("https://movie.douban.com/top250?start=%d&filter=" % (25 * i))

    # 統計該爬蟲的消耗時間
    t1 = time.time()
    print(‘*‘ * 50)

    for url in start_urls:
        download_picture(url)
    t2 = time.time()

    print(‘不使用多線程,總共耗時:%s‘%(t2-t1))
    print(‘*‘ * 50)

main()

其輸出結果如下:

**************************************************
不使用多線程,總共耗時:79.93260931968689
**************************************************

去E盤中的douban文件夾查看,如下圖:

技術分享圖片

??我們可以看到,在不使用多線程的情況下,這個爬蟲總共耗時約80s,完成了豆瓣Top250電影圖片的下載。

使用多線程

??接下來,我們使用多線程來下載豆瓣Top250電影圖片,其完整的Python代碼如下:

import time
import requests
import urllib.request
from bs4 import BeautifulSoup
from concurrent.futures import ThreadPoolExecutor, wait, ALL_COMPLETED

# 該函數用於下載圖片
# 傳入函數: 網頁的網址url
def download_picture(url):

    # 獲取網頁的源代碼
    r = requests.get(url)
    # 利用BeautifulSoup將獲取到的文本解析成HTML
    soup = BeautifulSoup(r.text, "lxml")
    # 獲取網頁中的電影圖片
    content = soup.find(‘div‘, class_=‘article‘)
    images = content.find_all(‘img‘)
    # 獲取電影圖片的名稱和下載地址
    picture_name_list = [image[‘alt‘] for image in images]
    picture_link_list = [image[‘src‘] for image in images]

    # 利用urllib.request..urlretrieve正式下載圖片
    for picture_name, picture_link in zip(picture_name_list, picture_link_list):
        urllib.request.urlretrieve(picture_link, ‘E://douban/%s.jpg‘ % picture_name)


def main():

    # 全部10個網頁
    start_urls = ["https://movie.douban.com/top250"]
    for i in range(1, 10):
        start_urls.append("https://movie.douban.com/top250?start=%d&filter=" % (25 * i))

    # 統計該爬蟲的消耗時間
    print(‘*‘ * 50)
    t3 = time.time()

    # 利用並發下載電影圖片
    executor = ThreadPoolExecutor(max_workers=10)  # 可以自己調整max_workers,即線程的個數
    # submit()的參數: 第一個為函數, 之後為該函數的傳入參數,允許有多個
    future_tasks = [executor.submit(download_picture, url) for url in start_urls]
    # 等待所有的線程完成,才進入後續的執行
    wait(future_tasks, return_when=ALL_COMPLETED)

    t4 = time.time()
    print(‘使用多線程,總共耗時:%s‘ % (t4 - t3))
    print(‘*‘ * 50)

main()

其輸出結果如下:

**************************************************
使用多線程,總共耗時:9.361606121063232
**************************************************

再去E盤中的douban文件夾查看,發現同樣也下載了250張電影圖片。

總結

??通過上述兩個爬蟲程序的對比,我們不難發現,同樣是下載豆瓣Top250電影,10個網頁中的圖片,在沒有使用多線程的情況下,總共耗時約80s,而在使用多線程(10個線程)的情況下,總共耗時約9.5秒,效率整整提高了約8倍。這樣的效率提升在爬蟲中無疑是令人興奮的。
??希望讀者在看了本篇博客後,也能嘗試著在自己的爬蟲中使用多線程,說不定會有意外的驚喜哦~~因為,大名鼎鼎的Python爬蟲框架Scrapy,也是使用多線程來提升爬蟲速度的哦!

註意:本人現已開通兩個微信公眾號: 因為Python(微信號為:python_math)以及輕松學會Python爬蟲(微信號為:easy_web_scrape), 歡迎大家關註哦~~

Python爬蟲之多線程下載豆瓣Top250電影圖片