濮阳杆衣贸易有限公司

主頁 > 知識(shí)庫 > Python異步爬蟲實(shí)現(xiàn)原理與知識(shí)總結(jié)

Python異步爬蟲實(shí)現(xiàn)原理與知識(shí)總結(jié)

熱門標(biāo)簽:哈爾濱ai外呼系統(tǒng)定制 海南400電話如何申請(qǐng) 廣告地圖標(biāo)注app 激戰(zhàn)2地圖標(biāo)注 唐山智能外呼系統(tǒng)一般多少錢 公司電話機(jī)器人 白銀外呼系統(tǒng) 騰訊外呼線路 陜西金融外呼系統(tǒng)

一、背景

默認(rèn)情況下,用get請(qǐng)求時(shí),會(huì)出現(xiàn)阻塞,需要很多時(shí)間來等待,對(duì)于有很多請(qǐng)求url時(shí),速度就很慢。因?yàn)樾枰粋€(gè)url請(qǐng)求的完成,才能讓下一個(gè)url繼續(xù)訪問。一種很自然的想法就是用異步機(jī)制來提高爬蟲速度。通過構(gòu)建線程池或者進(jìn)程池完成異步爬蟲,即使用多線程或者多進(jìn)程來處理多個(gè)請(qǐng)求(在別的進(jìn)程或者線程阻塞時(shí))。

import time 
#串形
 
def getPage(url):
    print("開始爬取網(wǎng)站",url)
    time.sleep(2)#阻塞
    print("爬取完成!??!",url)
 
 
urls = ['url1','url2','url3','url4','url5']
 
beginTime = time.time()#開始計(jì)時(shí)
 
for url in urls:
    getPage(url)
 
endTime= time.time()#結(jié)束計(jì)時(shí)
print("完成時(shí)間%d"%(endTime - beginTime))

下面通過模擬爬取網(wǎng)站來完成對(duì)多線程,多進(jìn)程,協(xié)程的理解。

二、多線程實(shí)現(xiàn)

import time 
#使用線程池對(duì)象
from multiprocessing.dummy import Pool
 
def getPage(url):
    print("開始爬取網(wǎng)站",url)
    time.sleep(2)#阻塞
    print("爬取完成?。?!",url)
 
 
urls = ['url1','url2','url3','url4','url5']
 
beginTime = time.time()#開始計(jì)時(shí)
 
#準(zhǔn)備開啟5個(gè)線程,并示例化對(duì)象
pool = Pool(5)
pool.map(getPage, urls)#urls是可迭代對(duì)象,里面每個(gè)參數(shù)都會(huì)給getPage方法處理
 
endTime= time.time()#結(jié)束計(jì)時(shí)
print("完成時(shí)間%d"%(endTime - beginTime))

完成時(shí)間只需要2s!!!!!!!!

線程池使用原則:適合處理耗時(shí)并且阻塞的操作

三、協(xié)程實(shí)現(xiàn)

單線程+異步協(xié)程?。。。。。。。。?!強(qiáng)烈推薦,目前流行的方式。

相關(guān)概念:

#%%
import time 
#使用協(xié)程
import asyncio
 
 
async def getPage(url):  #定義了一個(gè)協(xié)程對(duì)象,python中函數(shù)也是對(duì)象
    print("開始爬取網(wǎng)站",url)
    time.sleep(2)#阻塞
    print("爬取完成?。。?,url)
    
#async修飾的函數(shù)返回的對(duì)象    
c = getPage(11)
 
#創(chuàng)建事件對(duì)象
loop_event = asyncio.get_event_loop()
#注冊(cè)并啟動(dòng)looP
loop_event.run_until_complete(c)
 
#task對(duì)象使用,封裝協(xié)程對(duì)象c
'''
loop_event = asyncio.get_event_loop()
task = loop_event.create_task(c)
loop_event.run_until_complete(task)
'''
 
#Future對(duì)象使用,封裝協(xié)程對(duì)象c            用法和task差不多
'''
loop_event = asyncio.get_event_loop()
task       = asyncio.ensure_future(c)
loop_event.run_until_complete(task)
'''
 
#綁定回調(diào)使用
 
async def getPage2(url):  #定義了一個(gè)協(xié)程對(duì)象,python中函數(shù)也是對(duì)象
    print("開始爬取網(wǎng)站",url)
    time.sleep(2)#阻塞
    print("爬取完成?。?!",url)
    return url
    
#async修飾的函數(shù)返回的對(duì)象    
c2 = getPage2(2)
 
def callback_func(task):
    print(task.result()) #task.result()返回任務(wù)對(duì)象中封裝的協(xié)程對(duì)象對(duì)應(yīng)函數(shù)的返回值
 
 
#綁定回調(diào)
loop_event = asyncio.get_event_loop()
task       = asyncio.ensure_future(c2)
 
task.add_done_callback(callback_func)  #真正綁定,
loop_event.run_until_complete(task)

輸出:

四、多任務(wù)協(xié)程實(shí)現(xiàn)

import time 
#使用多任務(wù)協(xié)程
import asyncio
 
 
 
 
urls = ['url1','url2','url3','url4','url5']
 
 
 
async def getPage(url):  #定義了一個(gè)協(xié)程對(duì)象,python中函數(shù)也是對(duì)象
    print("開始爬取網(wǎng)站",url)
    #在異步協(xié)程中如果出現(xiàn)同步模塊相關(guān)的代碼,那么無法實(shí)現(xiàn)異步
    #time.sleep(2)#阻塞
    await asyncio.sleep(2)#遇到阻塞操作必須手動(dòng)掛起
    print("爬取完成!?。?,url)
    return url
    
 
beginTime = time.time()  
 
 
#任務(wù)列表,有多個(gè)任務(wù)
tasks = []
 
for url in urls:
    c = getPage(url)
    task = asyncio.ensure_future(c)#創(chuàng)建任務(wù)對(duì)象
    tasks.append(task)
loop = asyncio.get_event_loop()
loop.run_until_complete(asyncio.wait(tasks))#不能直接放task,需要封裝進(jìn)入asyncio,wait()方法中
 
endTime = time.time()   
print("完成時(shí)間%d"%(endTime - beginTime)) 

此時(shí)不能用time.sleep(2),用了還是10秒

對(duì)于真正爬取過程中,如在getPage()方法中真正爬取數(shù)據(jù)時(shí),即requests.get(url) ,它是基于同步方式實(shí)現(xiàn)。應(yīng)該使用異步網(wǎng)絡(luò)請(qǐng)求模塊aiohttp

參考下面代碼:

async def getPage(url):  #定義了一個(gè)協(xié)程對(duì)象,python中函數(shù)也是對(duì)象
    print("開始爬取網(wǎng)站",url)
    #在異步協(xié)程中如果出現(xiàn)同步模塊相關(guān)的代碼,那么無法實(shí)現(xiàn)異步
    #requests.get(url)#阻塞
    async with aiohttp.ClintSession() as session:
 
                     async with await  session.get(url) as response: #手動(dòng)掛起
 
                                       page_text =  await response.text() #.text()返回字符串,read()返回二進(jìn)制數(shù)據(jù),注意不是content
    print("爬取完成!??!",url)
    return page_text 

到此這篇關(guān)于Python異步爬蟲實(shí)現(xiàn)原理與知識(shí)總結(jié)的文章就介紹到這了,更多相關(guān)Python異步爬蟲內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

您可能感興趣的文章:
  • python多進(jìn)程和多線程究竟誰更快(詳解)
  • python爬蟲之線程池和進(jìn)程池功能與用法詳解
  • Python多線程、異步+多進(jìn)程爬蟲實(shí)現(xiàn)代碼
  • Python異步爬蟲多線程與線程池示例詳解

標(biāo)簽:四川 上海 益陽 黔西 黑龍江 惠州 常德 鷹潭

巨人網(wǎng)絡(luò)通訊聲明:本文標(biāo)題《Python異步爬蟲實(shí)現(xiàn)原理與知識(shí)總結(jié)》,本文關(guān)鍵詞  Python,異步,爬蟲,實(shí)現(xiàn),原理,;如發(fā)現(xiàn)本文內(nèi)容存在版權(quán)問題,煩請(qǐng)?zhí)峁┫嚓P(guān)信息告之我們,我們將及時(shí)溝通與處理。本站內(nèi)容系統(tǒng)采集于網(wǎng)絡(luò),涉及言論、版權(quán)與本站無關(guān)。
  • 相關(guān)文章
  • 下面列出與本文章《Python異步爬蟲實(shí)現(xiàn)原理與知識(shí)總結(jié)》相關(guān)的同類信息!
  • 本頁收集關(guān)于Python異步爬蟲實(shí)現(xiàn)原理與知識(shí)總結(jié)的相關(guān)信息資訊供網(wǎng)民參考!
  • 推薦文章
    华宁县| 福州市| 延川县| 万荣县| 鄂伦春自治旗| 沅江市| 平南县| 开阳县| 江西省| 灌云县| 塔城市| 商丘市| 墨脱县| 南靖县| 宣汉县| 盘山县| 沅陵县| 阿图什市| 虹口区| 凤冈县| 页游| 徐汇区| 遂昌县| 长葛市| 巫山县| 汽车| 兰州市| 新宁县| 防城港市| 乐至县| 泰安市| 南昌市| 涿州市| 盐津县| 松江区| 台北县| 平南县| 巴林右旗| 习水县| 平遥县| 虞城县|