博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
aiohttp 基于异步库的请求替代品
阅读量:6252 次
发布时间:2019-06-22

本文共 2171 字,大约阅读时间需要 7 分钟。

asyncio可以实现单线程的并发IO操作,如果仅用在客户端,发挥的威力并不大,把asyncio用在服务端,例如WEB服务器,由于HTTP连接就是IO操作,因此可以用单线程+coroutine实现多用户的高并发支持。

asyncio实现了TCP、UDP、SSL等协议,aiohttp则是基于asyncio实现的HTTP框架。

首先我们定义一个协同程序用来获取页面,并打印出来。我们使用asyncio.coroutine将一个方法装饰成一个协同程序,aiohttp.request是一个协同程序,所以他是一个可读方法。

@asyncio.coroutinedef print_page(url):    response = yield from aiohttp.request('GET', url)    #close断开的是网页与服务器的Connection:keep-alive        body = yield from response.read_and_close(dcode=True)    print(body)

如你所见,我们可以使用yield from从另一个协程中调用一个协程。为了从同步代码中调用一个协程,我们需要一个时间循环,我们可以通过asyncio.get_event_loop()得到一个标准的时间循环,之后使用它的loop.run_until_complete()方法启动协程,所以,为了使之前的协程运行我们只需要做:

loop = asyncio.get_evemnt_loop()loop.run_until_complete(print_page('http://xxxxx'))

一个有用的方法是asyncio.wait,通过它可以获取一个协程的列表,同时返回一个将它们包括在内的单独的协程,所以我们可以这样写:

loop.run_until_complete(asyncio.wait([print_page(url) for url in url_list]))

数据抓取

现在我们已经知道如何做异步请求,因此我们可以写一个数据抓取器,我们仅仅还需要一些工具来解析HTML

import aiohttpimport asynciodef get_content(html):    '''    处理HTML获取所需信息    '''async def print_magnet(page):    headers = {'key':'value'}    cookies = {'cookies_are': 'working'}    url = 'http://www.cnbligs.com/#p{}'.format(page)    async with aiohttp.ClientSession(cookies=cookies) as session:        async with session.get(url, headers=headers) as response:            content = get_content(await response.text())            print(await response.text())loop = asyncio.get_event_loop()tasks = asyncio.wait([print_magnet(page) for page in range(10)])loop.run_until_complete(tasks)

为了避免爬虫一次性的产生过多的请求导致账号/IP被封可以考虑使Semaphore控制同时的并发量,与我们熟悉的threading模块中的Semaphore(信号量)用法类似。

import aiohttpimpoer asyncioNUMBERS = range(12)URL = 'http://httpbin.org/get?a={}'sema = asyncio.Semaphore(3)async def fetch_async(a):    async with aiohttp.request('GET', URL.format(a)) as res:        data = await r.json()    return data['args']['a']    async def print_result(a):    with (await sema):        r = await fetch_async(a)        print('fetch({}) = {}'.foemat(a, r))        loop = asyncio.get_event_loop()f = asyncio.wait([print_result(num) for num in NUMBERS])loop.run_until_complete(f)

可以到后台看到并发受到了信号量的限制,同一时刻基本只处理三个请求。

转载于:https://www.cnblogs.com/coder-gao/p/7605225.html

你可能感兴趣的文章
xming + putty 搭建远程图形化ssh访问ubuntu 14.04
查看>>
php 自带过滤和转义函数
查看>>
javascript一些小技巧
查看>>
android 使用HttpURLConnection方式提交get/post请求
查看>>
CTR预估中GBDT与LR融合方案
查看>>
I00024 出钱买羽
查看>>
原生js实现点击下载图片
查看>>
WinCE winform 开发注意事项
查看>>
linux下文件的一些文件颜色的含义
查看>>
OLTP系统的Oracle RAC性能调优,索引分区极大提升提交性能
查看>>
Leetcode | Binary Tree Zigzag Level Order Traversal
查看>>
websotrm注册码
查看>>
迭代器(Iterable)和for..in..的三种协议
查看>>
Gephi可视化(一)——使用Gephi Toolkit创建Gephi应用
查看>>
判断浏览器是否为顶层窗口
查看>>
数据结构化与保存
查看>>
跨域iframe高度自适应(兼容IE/FF/OP/Chrome)
查看>>
没有发布过产品的程序员不知道什么是真正的软件
查看>>
图论 - Travel
查看>>
服务器设计笔记(3)-----消息队列
查看>>