day04-异步协程爬虫

1.使用线程池爬取

from multiprocessing.dummy import Pool
import time

s = time.time()
urls = ['www.111.com',
       'www.222.com',
       'www.333.com',
       'www.444.com',
       'www.555.com',
       'www.666.com']


def func(url):
   time.sleep(2)
   print('下载完成:', url)


if __name__ == '__main__':
   pool = Pool(3)
   pool.map(func, urls)
   pool.close()
   pool.join()
   print('运行时间:', time.time()-s)


# 总结:对应上例中的所面临的可能同时出现的上千甚至上万次的客户端请求,“线程池”或“连接池”或许可以缓解部分压力,但是不能解决所有问题。总之,多线程模型可以方便高效的解决小规模的服务请求,但面对大规模的服务请求,多线程模型也会遇到瓶颈,可以用非阻塞接口来尝试解决这个问题。

2.单线程+多任务协程

  • 协程

    • 在函数(特殊的函数内)定义的时候,如果使用了async修饰的话,则函数调用后会返回一个协程对象,并且函数内部的实现语句不是立即执行。

  • 任务对象

    • 任务对象就是对协程对象的进一步封装。任务对象==高级对象==特殊的函数

    • 任务对象是必须注册到事件循环对象中的

    • 给任务对象绑定回调:爬虫的数据解析中

  • 事件循环

    • 当做是一个容器,容器中必须存放任务对象

    • 当启动事件循环对象后,则事件循环对象会对其内部存储任务对象进行异步的执行

 

  • 1、定义协程

import asyncio


# # 定义一个协程
# async def execute(x):
#     print('Number:', x)
#
#
# # 获取到一个协程对象
# c = execute(1)
# print(c)
#
# # 创建一个事件循环对象
# loop = asyncio.get_event_loop()
#
# # 通过事件循环来创建一个任务对象,实际上就是将协程对象进一步封装
# # 它里面相比 coroutine 对象多了运行状态,比如 running、finished 等,我们可以用这些状态来获取协程对象的执行情况
# task = loop.create_task(c)
# print('状态:', task)
#
# # 启动事件循环
# loop.run_until_complete(task)
# print('状态:', task)


# 方式二:两个方法都一样,只不过后者不用借助loop(事件循环对象)来定义

async def execute(x):
   print('Number', x)
   return x


# 协程对象
c = execute(2)

# 创建任务对象
task = asyncio.ensure_future(c)
print(task)
# 创建一个事件循环对象
loop = asyncio.get_event_loop()

loop.run_until_complete(task)
print(task)

2.绑定回调:多数用于爬虫的数据解析

import asyncio
import requests


# 定义一个协程对象
async def request():
   url = 'https://www.baidu.com'
   status = requests.get(url)
   return status


def callback(task):
   print(task.result())


coroutine = request()

# 创建一个任务对象
task = asyncio.ensure_future(coroutine)
# 绑定回调方法
task.add_done_callback(callback)

# 创建事件循环对象
loop = asyncio.get_event_loop()
loop.run_until_complete(task)

3.单线程下的多任务协程


import requests
import asyncio


async def request():
   url = 'http://127.0.0.1:5000/'
   response = requests.get(url)
   return response.text


def callback(task):
   print(task.result())

# 把任务对象都存入列表
task = [asyncio.ensure_future(request()) for i in range(5)]

loop = asyncio.get_event_loop()
loop.run_until_complete(asyncio.wait(task))

for i in task:
   print(i.result())

4.案列:

"""先了解aiohttp库"""

 

posted @ 2020-07-22 23:51  老宝  阅读(89)  评论(0)    收藏  举报