单线程+异步协程(推荐):
event_loop:事件循环,相当于一个无限循环,我们可以把一些函数注册到这个事件循环上,
当满足某些条件的时候,函数就会被循环执行。
coroutine:协程对象,我们可以将协程对象注册到事件循环中,它会被事件循环调用。
我们可以使用 async 关键字来定义一个方法,这个方法在调用时不会立即被执行,而是返回
一个协程对象。
task:任务,它是对协程对象的进一步封装,包含了任务的各个状态。
future:代表将来执行或还没有执行的任务,实际上和 task 没有本质区别。
async 定义一个协程.
await 用来挂起阻塞方法的执行。
代码示例:
多任务异步协程
- import requests
- import asyncio
- import time
-
- 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'
- ]
-
- async def get_page(url):
- print('正在下载',url)
- #requests.get是基于同步,必须使用基于异步的网络请求模块进行指定url的请求发送
- #aiohttp:基于异步网络请求的模块
- response = requests.get(url=url)
- print('下载完毕:',response.text)
-
- 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)
-
多任务协程
- import asyncio
- import time
-
- async def request(url):
- print('正在下载',url)
- #在异步协程中如果出现了同步模块相关的代码,那么就无法实现异步。
- # time.sleep(2)
- #当在asyncio中遇到阻塞操作必须进行手动挂起
- await asyncio.sleep(2)
- print('下载完毕',url)
-
- start = time.time()
- urls = [
- 'www.baidu.com',
- 'www.sogou.com',
- 'www.goubanjia.com'
- ]
-
- #任务列表:存放多个任务对象
- stasks = []
- for url in urls:
- c = request(url)
- task = asyncio.ensure_future(c)
- stasks.append(task)
-
- loop = asyncio.get_event_loop()
- #需要将任务列表封装到wait中
- loop.run_until_complete(asyncio.wait(stasks))
-
- print(time.time()-start)
-
aiohttp+多任务异步协程实现异步爬虫
- #环境安装:pip install aiohttp
- #使用该模块中的ClientSession
- import requests
- import asyncio
- import time
- import aiohttp
-
- 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',
- # 'http://127.0.0.1:5000/bobo', 'http://127.0.0.1:5000/jay', 'http://127.0.0.1:5000/tom',
- # 'http://127.0.0.1:5000/bobo', 'http://127.0.0.1:5000/jay', 'http://127.0.0.1:5000/tom',
- # 'http://127.0.0.1:5000/bobo', 'http://127.0.0.1:5000/jay', 'http://127.0.0.1:5000/tom',
- #
- # ]
- from multiprocessing.dummy import Pool
- pool = Pool(2)
-
- urls = []
- for i in range(10):
- urls.append('http://127.0.0.1:5000/bobo')
- print(urls)
- async def get_page(url):
- async with aiohttp.ClientSession() as session:
- #get()、post():
- #headers,params/data,proxy='http://ip:port'
- async with await session.get(url) as response:
- #text()返回字符串形式的响应数据
- #read()返回的二进制形式的响应数据
- #json()返回的就是json对象
- #注意:获取响应数据操作之前一定要使用await进行手动挂起
- page_text = await response.text()
- print(page_text)
-
- 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)