爬蟲(chóng)項(xiàng)目介紹
??本次爬蟲(chóng)項(xiàng)目將爬取豆瓣Top250電影的圖片晴弃,其網(wǎng)址為:https://movie.douban.com/top250, 具體頁(yè)面如下圖所示:
??本次爬蟲(chóng)項(xiàng)目將分別不使用多線(xiàn)程和使用多線(xiàn)程來(lái)完成,通過(guò)兩者的對(duì)比,顯示出多線(xiàn)程在爬蟲(chóng)項(xiàng)目中的巨大優(yōu)勢(shì)。本文所使用的多線(xiàn)程用到了concurrent.futures模塊科盛,該模塊是Python中最廣為使用的并發(fā)庫(kù),它可以非常方便地將任務(wù)并行化菜皂。在concurrent.futures模塊中土涝,共有兩種并發(fā)模塊,分別如下:
- 多線(xiàn)程模式:ThreadPoolExecutor幌墓,適合 IO密集型任務(wù)但壮;
- 多進(jìn)程模式:ProcessPoolExecutor,適合計(jì)算密集型任務(wù)常侣。
具體的關(guān)于該模塊的介紹可以參考其官方網(wǎng)址:https://docs.python.org/3/library/concurrent.futures.html 蜡饵。
??本次爬蟲(chóng)項(xiàng)目將會(huì)用到concurrent.futures模塊中的ThreadPoolExecutor類(lèi),多線(xiàn)程下載豆瓣Top250電影圖片胳施。下面將會(huì)給出本次爬蟲(chóng)項(xiàng)目分別不使用多線(xiàn)程和使用多線(xiàn)程的對(duì)比溯祸,以此來(lái)展示多線(xiàn)程在爬蟲(chóng)中的巨大優(yōu)勢(shì)。
不使用多線(xiàn)程
??首先舞肆,我們不使用多線(xiàn)程來(lái)下載豆瓣Top250電影圖片焦辅,其完整的Python代碼如下:
import time
import requests
import urllib.request
from bs4 import BeautifulSoup
# 該函數(shù)用于下載圖片
# 傳入函數(shù): 網(wǎng)頁(yè)的網(wǎng)址url
def download_picture(url):
# 獲取網(wǎng)頁(yè)的源代碼
r = requests.get(url)
# 利用BeautifulSoup將獲取到的文本解析成HTML
soup = BeautifulSoup(r.text, "lxml")
# 獲取網(wǎng)頁(yè)中的電影圖片
content = soup.find('div', class_='article')
images = content.find_all('img')
# 獲取電影圖片的名稱(chēng)和下載地址
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個(gè)網(wǎng)頁(yè)
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))
# 統(tǒng)計(jì)該爬蟲(chóng)的消耗時(shí)間
t1 = time.time()
print('*' * 50)
for url in start_urls:
download_picture(url)
t2 = time.time()
print('不使用多線(xiàn)程,總共耗時(shí):%s'%(t2-t1))
print('*' * 50)
main()
其輸出結(jié)果如下:
**************************************************
不使用多線(xiàn)程椿胯,總共耗時(shí):79.93260931968689
**************************************************
去E盤(pán)中的douban文件夾查看筷登,如下圖:
??我們可以看到,在不使用多線(xiàn)程的情況下哩盲,這個(gè)爬蟲(chóng)總共耗時(shí)約80s前方,完成了豆瓣Top250電影圖片的下載。
使用多線(xiàn)程
??接下來(lái)廉油,我們使用多線(xiàn)程來(lái)下載豆瓣Top250電影圖片惠险,其完整的Python代碼如下:
import time
import requests
import urllib.request
from bs4 import BeautifulSoup
from concurrent.futures import ThreadPoolExecutor, wait, ALL_COMPLETED
# 該函數(shù)用于下載圖片
# 傳入函數(shù): 網(wǎng)頁(yè)的網(wǎng)址url
def download_picture(url):
# 獲取網(wǎng)頁(yè)的源代碼
r = requests.get(url)
# 利用BeautifulSoup將獲取到的文本解析成HTML
soup = BeautifulSoup(r.text, "lxml")
# 獲取網(wǎng)頁(yè)中的電影圖片
content = soup.find('div', class_='article')
images = content.find_all('img')
# 獲取電影圖片的名稱(chēng)和下載地址
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個(gè)網(wǎng)頁(yè)
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))
# 統(tǒng)計(jì)該爬蟲(chóng)的消耗時(shí)間
print('*' * 50)
t3 = time.time()
# 利用并發(fā)下載電影圖片
executor = ThreadPoolExecutor(max_workers=10) # 可以自己調(diào)整max_workers,即線(xiàn)程的個(gè)數(shù)
# submit()的參數(shù): 第一個(gè)為函數(shù), 之后為該函數(shù)的傳入?yún)?shù)抒线,允許有多個(gè)
future_tasks = [executor.submit(download_picture, url) for url in start_urls]
# 等待所有的線(xiàn)程完成班巩,才進(jìn)入后續(xù)的執(zhí)行
wait(future_tasks, return_when=ALL_COMPLETED)
t4 = time.time()
print('使用多線(xiàn)程,總共耗時(shí):%s' % (t4 - t3))
print('*' * 50)
main()
其輸出結(jié)果如下:
**************************************************
使用多線(xiàn)程嘶炭,總共耗時(shí):9.361606121063232
**************************************************
再去E盤(pán)中的douban文件夾查看抱慌,發(fā)現(xiàn)同樣也下載了250張電影圖片。
總結(jié)
??通過(guò)上述兩個(gè)爬蟲(chóng)程序的對(duì)比旱物,我們不難發(fā)現(xiàn)遥缕,同樣是下載豆瓣Top250電影,10個(gè)網(wǎng)頁(yè)中的圖片宵呛,在沒(méi)有使用多線(xiàn)程的情況下单匣,總共耗時(shí)約80s,而在使用多線(xiàn)程(10個(gè)線(xiàn)程)的情況下宝穗,總共耗時(shí)約9.5秒户秤,效率整整提高了約8倍。這樣的效率提升在爬蟲(chóng)中無(wú)疑是令人興奮的逮矛。
??希望讀者在看了本篇博客后鸡号,也能?chē)L試著在自己的爬蟲(chóng)中使用多線(xiàn)程,說(shuō)不定會(huì)有意外的驚喜哦~~因?yàn)樾攵Γ竺ΧΦ腜ython爬蟲(chóng)框架Scrapy鲸伴,也是使用多線(xiàn)程來(lái)提升爬蟲(chóng)速度的哦府蔗!
注意:本人現(xiàn)已開(kāi)通兩個(gè)微信公眾號(hào): 因?yàn)镻ython(微信號(hào)為:python_math)以及輕松學(xué)會(huì)Python爬蟲(chóng)(微信號(hào)為:easy_web_scrape), 歡迎大家關(guān)注哦~~