python如何提升爬蟲效率
單線程+多任務(wù)異步協(xié)程
- 協(xié)程
在函數(shù)(特殊函數(shù))定義的時候,使用async修飾,函數(shù)調(diào)用后,內(nèi)部語句不會立即執(zhí)行,而是會返回一個協(xié)程對象
- 任務(wù)對象
任務(wù)對象=高級的協(xié)程對象(進(jìn)一步封裝)=特殊的函數(shù)
任務(wù)對象必須要注冊到時間循環(huán)對象中
給任務(wù)對象綁定回調(diào):爬蟲的數(shù)據(jù)解析中
- 事件循環(huán)
當(dāng)做是一個裝載任務(wù)對象的容器
當(dāng)啟動事件循環(huán)對象的時候,存儲在內(nèi)的任務(wù)對象會異步執(zhí)行
- 特殊函數(shù)內(nèi)部不能寫不支持異步請求的模塊,如time,requests...否則雖然不報錯但實(shí)現(xiàn)不了異步
time.sleep -- asyncio.sleep
requests -- aiohttp
import asyncio import time start_time = time.time() async def get_request(url): await asyncio.sleep(2) print(url,'下載完成!') urls = [ 'www.1.com', 'www.2.com', ] task_lst = [] # 任務(wù)對象列表 for url in urls: c = get_request(url) # 協(xié)程對象 task = asyncio.ensure_future(c) # 任務(wù)對象 # task.add_done_callback(...) # 綁定回調(diào) task_lst.append(task) loop = asyncio.get_event_loop() # 事件循環(huán)對象 loop.run_until_complete(asyncio.wait(task_lst)) # 注冊,手動掛起
線程池+requests模塊
# 線程池 import time from multiprocessing.dummy import Pool start_time = time.time() url_list = [ 'www.1.com', 'www.2.com', 'www.3.com', ] def get_request(url): print('正在下載...',url) time.sleep(2) print('下載完成!',url) pool = Pool(3) pool.map(get_request,url_list) print('總耗時:',time.time()-start_time)
兩個方法提升爬蟲效率
起一個flask服務(wù)端
from flask import Flask import time app = Flask(__name__) @app.route('/bobo') def index_bobo(): time.sleep(2) return 'hello bobo!' @app.route('/jay') def index_jay(): time.sleep(2) return 'hello jay!' @app.route('/tom') def index_tom(): time.sleep(2) return 'hello tom!' if __name__ == '__main__': app.run(threaded=True)
aiohttp模塊+單線程多任務(wù)異步協(xié)程
import asyncio import aiohttp import requests import time start = time.time() async def get_page(url): # page_text = requests.get(url=url).text # print(page_text) # return page_text async with aiohttp.ClientSession() as s: #生成一個session對象 async with await s.get(url=url) as response: page_text = await response.text() print(page_text) return page_text urls = [ 'http://127.0.0.1:5000/bobo', 'http://127.0.0.1:5000/jay', 'http://127.0.0.1:5000/tom', ] tasks = [] for url in urls: c = get_page(url) task = asyncio.ensure_future(c) tasks.append(task) loop = asyncio.get_event_loop() loop.run_until_complete(asyncio.wait(tasks)) end = time.time() print(end-start) # 異步執(zhí)行! # hello tom! # hello bobo! # hello jay! # 2.0311079025268555
''' aiohttp模塊實(shí)現(xiàn)單線程+多任務(wù)異步協(xié)程 并用xpath解析數(shù)據(jù) ''' import aiohttp import asyncio from lxml import etree import time start = time.time() # 特殊函數(shù):請求的發(fā)送和數(shù)據(jù)的捕獲 # 注意async with await關(guān)鍵字 async def get_request(url): async with aiohttp.ClientSession() as s: async with await s.get(url=url) as response: page_text = await response.text() return page_text # 返回頁面源碼 # 回調(diào)函數(shù),解析數(shù)據(jù) def parse(task): page_text = task.result() tree = etree.HTML(page_text) msg = tree.xpath('/html/body/ul//text()') print(msg) urls = [ 'http://127.0.0.1:5000/bobo', 'http://127.0.0.1:5000/jay', 'http://127.0.0.1:5000/tom', ] tasks = [] for url in urls: c = get_request(url) task = asyncio.ensure_future(c) task.add_done_callback(parse) #綁定回調(diào)函數(shù)! tasks.append(task) loop = asyncio.get_event_loop() loop.run_until_complete(asyncio.wait(tasks)) end = time.time() print(end-start)
requests模塊+線程池
import time import requests from multiprocessing.dummy import Pool start = time.time() urls = [ 'http://127.0.0.1:5000/bobo', 'http://127.0.0.1:5000/jay', 'http://127.0.0.1:5000/tom', ] def get_request(url): page_text = requests.get(url=url).text print(page_text) return page_text pool = Pool(3) pool.map(get_request, urls) end = time.time() print('總耗時:', end-start) # 實(shí)現(xiàn)異步請求 # hello jay! # hello bobo! # hello tom! # 總耗時: 2.0467123985290527
小結(jié)
- 爬蟲的加速目前掌握了兩種方法:
aiohttp模塊+單線程多任務(wù)異步協(xié)程
requests模塊+線程池
- 爬蟲接觸的模塊有三個:
requests
urllib
aiohttp
- 接觸了一下flask開啟服務(wù)器
以上就是python如何提升爬蟲效率的詳細(xì)內(nèi)容,更多關(guān)于python提升爬蟲效率的資料請關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
在django中form的label和verbose name的區(qū)別說明
這篇文章主要介紹了在django中form的label和verbose name的區(qū)別說明,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧2020-05-05Python中Parser的超詳細(xì)用法實(shí)例
Parser模塊為Python的內(nèi)部解析器和字節(jié)碼編譯器提供了一個接口,該接口的主要目的是允許Python代碼編輯Python表達(dá)式的分析樹并從中創(chuàng)建可執(zhí)行代碼,這篇文章主要給大家介紹了關(guān)于Python中Parser超詳細(xì)用法的相關(guān)資料,需要的朋友可以參考下2022-07-07python密碼學(xué)換位密碼及換位解密轉(zhuǎn)置加密教程
這篇文章主要為大家介紹了python密碼學(xué)換位密碼及換位解密轉(zhuǎn)置加密教程,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2022-05-05Django contenttypes 框架詳解(小結(jié))
這篇文章主要介紹了Django contenttypes 框架詳解(小結(jié)),小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧2018-08-08python 調(diào)試?yán)渲R(小結(jié))
這篇文章主要介紹了python 調(diào)試?yán)渲R(小結(jié)),文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2019-11-11基于python實(shí)現(xiàn)坦克大戰(zhàn)游戲
這篇文章主要為大家詳細(xì)介紹了基于python實(shí)現(xiàn)坦克大戰(zhàn)游戲,文中示例代碼介紹的非常詳細(xì),具有一定的參考價值,感興趣的小伙伴們可以參考一下2020-10-10詳解如何將Python可執(zhí)行文件(.exe)反編譯為Python腳本
將?Python?可執(zhí)行文件(.exe)反編譯為?Python?腳本是一項(xiàng)有趣的技術(shù)挑戰(zhàn),可以幫助我們理解程序的工作原理,下面我們就來看看具體實(shí)現(xiàn)步驟吧2024-03-03