一 . 線程池和進程池
可以適當的使用,在大量的IO情況下有更好的方法
import time
from multiprocessing.dummy import Pool
def request(url):print('正在下載->',url)time.sleep(2)print('下載完畢->',url)
start = time.time()
urls = ['www.baidu.com','www.taobao.com','www.sougou.com'
]
pool = Pool(3)
pool.map(request,urls)print('總耗時->',time.time()-start)
二 . 單線程+異步協程(高性能的異步爬蟲)
event_loop:相當于無線循環,我們可以把特殊的函數注冊到這個時間循環上,異步執行
coroutine:協程,就是被async修飾的函數
task:任務,它是對協程進一步封裝,包含了協程的各個狀態
future:將要執行的任務
async/await,這兩個是需要重點了解的
事件循環
import asyncio
async def hello(name):print('hello->'+ name)
# 獲取一個協程對象
c = hello('attila')# 創建一個事件循環
loop = asyncio.get_event_loop()# 將協程對象注冊到事件循環中,并且啟動事件循環對象
loop.run_until_complete(c)
task
import asyncio
async def hello(name):print('hello->'+ name)
# 獲取一個協程對象
c = hello('attila')# 創建一個事件循環
loop = asyncio.get_event_loop()# 把協程封裝到task中
task = loop.create_task(c)
print(task) # Task pending
# 將協程對象注冊到事件循環中,并且啟動事件循環對象
loop.run_until_complete(task)
print(task) # Task finished
future
import asyncio
async def hello(name):print('hello->'+ name)
# 獲取一個協程對象
c = hello('attila')# 把協程封裝到task中
task = asyncio.ensure_future(c)# 將協程對象注冊到事件循環中,并且啟動事件循環對象
loop.run_until_complete(task)
綁定回調
import asynciodef call_back(task):print('---->',task.result())
async def hello(name):print('hello->'+ name)return name
# 獲取一個協程對象
c = hello('attila')# 把協程封裝到task中
task = asyncio.ensure_future(c)
# 給任務綁定一個回調函數,這個call_back里面的參數就是綁定回到函數的task
task.add_done_callback(call_back)
# 將協程對象注冊到事件循環中,并且啟動事件循環對象
loop.run_until_complete(task)
多任務異步協程(這里需要用到一個新模塊aiohttp,一定不能是requests,因為requests是一個非異步模塊)
pip install aiohttp
import aiohttp
import asyncioasync def get_page(url):async with aiohttp.ClientSession() as session:async with await session.get(url=url) as response: # 只要有io操作的地方就要掛起(await)page_text = await response.text()print(page_text)start = time.time()
# 這里的url是自己在后臺搭建的服務器,沒給url都是time.sleep(2)
urls = ['http://127.0.0.1:5000/cat','http://127.0.0.1:5000/dog','http://127.0.0.1:5000/monkey','http://127.0.0.1:5000/cat','http://127.0.0.1:5000/dog','http://127.0.0.1:5000/monkey','http://127.0.0.1:5000/cat','http://127.0.0.1:5000/dog','http://127.0.0.1:5000/monkey',
]
tasks = []
loop = asyncio.get_event_loop()
for url in urls:c = get_page(url)task = asyncio.ensure_future(c)tasks.append(task)
loop.run_until_complete(asyncio.wait(tasks))
print('總耗時->',time.time()-start) # 總耗時-> 2.053046464920044
?
?