python ahttp:简单、高效、异步requests请求模块-程序员宅基地

技术标签: python  

ahttp:简单、高效、异步requests请求模块

ahttp 是一个所有的http连接请求均使用协程的方式。 使请求过程中 IO 操作交给其他硬件,而CPU专注于处理计算型任务,可以大量的节约等待的时间。

适用版本: PYTHON 3.7

快速开始

安装

你可以通过以下方式快速安装:

pip install ahttp

单个请求

使用是非常简单的:

import ahttp 

url = "http://httpbin.org/headers" 

构造一个get请求对象:

req = ahttp.get(url)

执行请求:

res = res.run()

打印出请求得到的文本:

print(res.text)

如果你使用过requests,那么ahttp的使用方式基本上和它一致,只不过requests请求是同步,而ahttp的请求是异步。不同的是requests可以直接请求,而由于ahttp是异步的,所以需要构造好请求之后进行一次“执行”

多个请求

单个请求的时候,ahttp的异步是无法体现出来的,多个请求的时候则能很好的体现异步的不同和快速

构造一些请求(这里以获取 豆瓣电影排行250 为例):

urls = [ f"https://movie.douban.com/top250?start={i*25}" for i in range(10) ]
reqs = [ahttp.get(url) for url in urls]

这里的reqs里存放了10个请求对象,但是还未执行请求,通过ahttp.run(reqs)执行这些请求:

resps = ahttp.run(reqs)

运行上面命令后,这10个请求会以异步的形式执行,打印执行结果:

print(resps)

#输出结果如下:
[<AhttpResponse status[200] url=[https://movie.douban.com/top250?start=0]>, 
<AhttpResponse status[200] url=[https://movie.douban.com/top250?start=25]>, 
<AhttpResponse status[200] url=[https://movie.douban.com/top250?start=75]>, 
<AhttpResponse status[200] url=[https://movie.douban.com/top250?start=50]>, 
<AhttpResponse status[200] url=[https://movie.douban.com/top250?start=100]>, 
<AhttpResponse status[200] url=[https://movie.douban.com/top250?start=125]>, 
<AhttpResponse status[200] url=[https://movie.douban.com/top250?start=150]>, 
<AhttpResponse status[200] url=[https://movie.douban.com/top250?start=175]>, 
<AhttpResponse status[200] url=[https://movie.douban.com/top250?start=200]>, 
<AhttpResponse status[200] url=[https://movie.douban.com/top250?start=225]>]

查看第一个请求的html:

print(resps[0].text)

多个请求(使用session)

和使用ahttp构造请求list请求相比,使用session请求速度更快,而且共享cookies,因为session创建的是一个持久的链接:

urls = [ f"https://movie.douban.com/top250?start={i*25}" for i in range(10) ]
sess = ahttp.Session()
reqs = [sess.get(url) for url in urls]

resps = ahttp.run(reqs)
print(resps)

输出结果如下:

[<AhttpResponse status[200] url=[https://movie.douban.com/top250?start=25]>,
 <AhttpResponse status[200] url=[https://movie.douban.com/top250?start=50]>, 
 <AhttpResponse status[200] url=[https://movie.douban.com/top250?start=75]>, 
 <AhttpResponse status[200] url=[https://movie.douban.com/top250?start=0]>, 
 <AhttpResponse status[200] url=[https://movie.douban.com/top250?start=100]>, 
 <AhttpResponse status[200] url=[https://movie.douban.com/top250?start=125]>, 
 <AhttpResponse status[200] url=[https://movie.douban.com/top250?start=150]>, 
 <AhttpResponse status[200] url=[https://movie.douban.com/top250?start=175]>, 
 <AhttpResponse status[200] url=[https://movie.douban.com/top250?start=225]>, 
 <AhttpResponse status[200] url=[https://movie.douban.com/top250?start=200]>]

有序返回

reqs列表完成请求之后,得到的是一个resps列表。由于是异步请求,所以得到的resps并不是按照reqs请求的顺序排列的。豆瓣排行我们需要按照顺序处理,只需要在ahttp.run添加一个参数order

resps = ahttp.run(reqs, order=True)

提取文本

ahttp内置了使用requests_html来处理文本,使文本处理非常的简单
例如提取第一个链接中的电影title:

resp = resps[0]
titles =[i[0] for i in resp.html.search_all('<span class="title">{}</span>')]

得到的结果如下:

['蝙蝠侠:黑暗骑士', '&nbsp;/&nbsp;The Dark Knight', '活着', '控方证人', 
'&nbsp;/&nbsp;Witness for the Prosecution', '乱世佳人', '&nbsp;/&nbsp;Gone with the Wind', '少年派的奇幻漂流',
 '&nbsp;/&nbsp;Life of Pi', '摔跤吧!爸爸', '&nbsp;/&nbsp;Dangal', '指环王3:王者无敌', 
 '&nbsp;/&nbsp;The Lord of the Rings: The Return of the King', '飞屋环游记', 
 '&nbsp;/&nbsp;Up', '鬼子来了', '十二怒汉', '&nbsp;/&nbsp;12 Angry Men', '天空之城', 
 '&nbsp;/&nbsp;天空の城ラピュタ', '天堂电影院', '&nbsp;/&nbsp;Nuovo Cinema Paradiso', '寻梦环游记', '&nbsp;/&nbsp;Coco', '大话西游之月光宝盒',
  '&nbsp;/&nbsp;西遊記第壹佰零壹回之月光寶盒', '末代皇帝', '&nbsp;/&nbsp;The Last Emperor', '哈尔的移动城堡', '&nbsp;/&nbsp;ハウルの動く城',
   '罗马假日', '&nbsp;/&nbsp;Roman Holiday', '搏击俱乐部', '&nbsp;/&nbsp;Fight Club',
    '闻香识女人', '&nbsp;/&nbsp;Scent of a Woman', '素媛', '&nbsp;/&nbsp;소원', '辩护人', 
    '&nbsp;/&nbsp;변호인', '窃听风暴', '&nbsp;/&nbsp;Das Leben der Anderen', '何以为家', 
    '&nbsp;/&nbsp;كفرناحوم', '死亡诗社', '&nbsp;/&nbsp;Dead Poets Society', '两杆大烟枪', 
    '&nbsp;/&nbsp;Lock, Stock and Two Smoking Barrels']

有关更多文本处理,请参考 requests_html 文本处理

基本使用

发送请求

  • 导入模块

      import ahttp
    
  • 把需要请求的连接添加到任务中

      urls = [
          'http://www.heroku.com',
          'http://python-tablib.org',
          'http://httpbin.org',
          'http://python-requests.org',
          'http://fakedomain/',
          'http://kennethreitz.com'
      ]
    
      tasks=(ahttp.get(i) for i in urls)
    
  • 或者,你可能需要构建这样的一组任务

      tasks=[ahttp.get(url1), ahttp.post(url2, data=data), ahttp.post(url3), ahttp.get(url4)]
    
  • 然后,送他们去工作

      ahttp.run(tasks)
    
  • 除了 POST 请求和 GET 请求之外,你也可以发送其他请求

      ahttp.put('http://httpbin.org/put', data=b'data')
      ahttp.delete('http://httpbin.org/delete')
      ahttp.head('http://httpbin.org/get')
      ahttp.options('http://httpbin.org/get')
      ahttp.patch('http://httpbin.org/patch', data=b'data')
    

响应内容

  • results = ahttp.run(tasks) 会让我们得到响应对象的集合

      [<AhttpResponse [status 200]>, <AhttpResponse [status 200]>, <AhttpResponse [status 200]>, <AhttpResponse [status 200]>, None, <AhttpResponse [status 200]>]
    
  • 我们现在取出其中一个响应的对象

      resp = results[0]
    
  • 查看这个对象是哪个连接响应来的

      resp.url
    
  • 查看响应的请求方式(POST, GET或者其他)

      resp.method
    
  • 查看字节形式的响应文本

      resp.content
    
  • 查看字符串形式响应的文本

      resp.text
    
  • 查看响应Cookies

      resp.cookies
    
  • 查看响应状态码

      resp.status
    
  • 查看响应头

      resp.headers
    
  • 如果你对 aiohttp 这个协程http库比较熟悉,那么你也可以通过获得其原生的响应对象来获得想要的内容,原生的响应对象的方法和属性具体可参照 aiohttp 的官方文档

      resp.raw #返回原生响应对象
    

在URL中传递参数

你可以通过以下几种方式给URL传递参数

  • dict传参

      params1 = {'key1': 'value1', 'key2': 'value2'} 
      params2 = [('key', 'value1'), ('key', 'value2')]
    
      tasks=[ahttp.get(url, params = params1), ahttp.get(url, params = params2)]
    
  • POST请求传递 json

      import json
    
      params = {'key1': 'value1', 'key2': 'value2'}
      tasks=[ahttp.get(url, params = json.dumps(params)), ]
    

POST数据的几种方式

  • 模拟表单提交

      data = {'key1': 'value1', 'key2': 'value2'}
      
      tasks=[ahttp.post(url, data = data)]
    
  • POST json 数据

      import json
    
      data = {'key1': 'value1', 'key2': 'value2'}
      tasks=[ahttp.get(url, json=data)
    
  • POST 文件和预压缩数据,请参考我的另一篇博客

      http://blog.csdn.net/getcomputerstyle/article/details/71515331
    

使用 Session

使用session后,将使用keep-alive,能够很大大大程度上加快连接的速度

  • 你可以在创建任务之前,创建一个携带session的ahttp对象

      sess = ahttp.Session()
    
  • 然后一切又和以前一样, 创建一个任务

      tasks = (sess.get(i) for i in urls)
    
  • 使用的同一个sess 则是使用的同一个session,它们有着共同的Cookie,不同的session请求对象也可以一起发出请求

      sess1 = ahttp.Session()
      sess2 = ahttp.Session()
      ...
      task1 = [sess1.get(i) for i in urls1]
      task2 = [sess2.post(i) for i in urls2]
      task3 = [ahttp.get(i) for i in urls3]
      tasks = task1 + task2 + task3
      
      ahttp.run(tasks)
    

创建单个请求

task = ahttp.get('https://www.google.com')
task.run()

或者可以这样写

result = ahttp.get('https://www.google.com').run()

自定义请求头

  • 自定义请求头可直接作为参数传递到对象中,为每一个连接赋予请求头

      headers = {'content-type': 'application/json'}
      ...
      tasks = [ ahttp.get(url=url, headers=headers), ...]
    
  • 给session设置请求头

      headers = {'content-type': 'application/json'}
      ...
      sess = ahttp.Session()
      sess.headers = {
      	...
      }
    

自定义 Cookie

  • session自定义Cookie

      cookies = {'content-type': 'application/json'}
      ...
      sess = ahttp.Session()
      sess.cookies = {...}
    
  • ahttp连接设置Cookie

      headers = {'PHPSESSIONID': '0XJFDFJJHFGKALDAS'}
      ...
      tasks = [ ahttp.get(url=url, cookies=cookies), ...]
    

自定义 encoding

ahttp采用了自动识别的编码方式,能够自动识别的编码如下:

国际(Unicode)
UTF-8
UTF-16BE / UTF-16LE
UTF-32BE / UTF-32LE / X-ISO-10646-UCS-4-34121 / X-ISO-10646-UCS-4-21431
阿拉伯
ISO-8859-6
WINDOWS-1256
保加利亚语
ISO-8859-5
WINDOWS-1251
中文
ISO-2022-CN
BIG5
EUC-TW
GB18030
HZ-GB-2312
克罗地亚:
ISO-8859-2
ISO-8859-13
ISO-8859-16
Windows的1250
IBM852
MAC-CENTRALEUROPE
捷克
Windows的1250
ISO-8859-2
IBM852
MAC-CENTRALEUROPE
丹麦
ISO-8859-1
ISO-8859-15
WINDOWS-1252
英语
ASCII
世界语
ISO-8859-3
爱沙尼亚语
ISO-8859-4
ISO-8859-13
ISO-8859-13
Windows的1252
Windows的1257
芬兰
ISO-8859-1
ISO-8859-4
ISO-8859-9
ISO-8859-13
ISO-8859-15
WINDOWS-1252
法国
ISO-8859-1
ISO-8859-15
WINDOWS-1252
德语
ISO-8859-1
WINDOWS-1252
希腊语
ISO-8859-7
WINDOWS-1253
希伯来语
ISO-8859-8
WINDOWS-1255
匈牙利:
ISO-8859-2
WINDOWS-1250
爱尔兰盖尔语
ISO-8859-1
ISO-8859-9
ISO-8859-15
WINDOWS-1252
意大利
ISO-8859-1
ISO-8859-3
ISO-8859-9
ISO-8859-15
WINDOWS-1252
日本
ISO-2022-JP
SHIFT_JIS
EUC-JP
朝鲜的
ISO-2022-KR
EUC-KR / UHC
立陶宛
ISO-8859-4
ISO-8859-10
ISO-8859-13
拉脱维亚
ISO-8859-4
ISO-8859-10
ISO-8859-13
马耳他语
ISO-8859-3
抛光:
ISO-8859-2
ISO-8859-13
ISO-8859-16
Windows的1250
IBM852
MAC-CENTRALEUROPE
葡萄牙语
ISO-8859-1
ISO-8859-9
ISO-8859-15
WINDOWS-1252
罗马尼亚:
ISO-8859-2
ISO-8859-16
Windows的1250
IBM852
俄语
ISO-8859-5
KOI8-R
WINDOWS-1251
MAC-CYRILLIC
IBM866
IBM855
斯洛伐克
Windows的1250
ISO-8859-2
IBM852
MAC-CENTRALEUROPE
斯洛文尼亚
ISO-8859-2
ISO-8859-16
Windows的1250
IBM852
中号

设置代理

  • 无验证代理

      proxy = "http://some.proxy.com"
      ...
      tasks = [ahttp(url, proxy = proxy), ...]
    
  • 需要授权的代理

      proxy = "http://some.proxy.com"
      ...
      tasks = [ahttp(url, proxy = proxy, proxy_auth=proxy_auth), ...]	
    
  • 或者通过这种方式

      ...
      tasks = [ahttp(url, proxy="http://user:[email protected]"), ...]	
    
  • socks代理

      proxy = {
          "http":"socks5://127.0.0.1:1080",
          "https":"socks5h://127.0.0.1:1080"
      }
      ahttp.get(url, proxy=proxy)
    

修改最大并发的数量

连接池的默认值为 2,意思是同时最多有 2 个协程及其周期在运转,你可以通过下列代码进行修改,但是请注意,不要超过1024个。 如果服务器响应很慢,那么开的越多越好,可以改成 100 -200 , 如果服务器响应很快,那么pool =2 和 pool = 100 几乎是没什么区别的。因为等待都在 IO 操作上

	...
	results = ahttp.run(tasks, pool = 100) #将连接池改为100

回调函数

你可以通过给任务对象添加回调函数的方式以指定当前任务完成执行的函数

def callback(ahttp_response):
	ahttp_response # <AhttpResponse [status 200]>
	ahttp_response.status # 200
...
tasks=[ahttp.get(url, callback = callback), ...]

设置超时

task = ahttp.get(url,..., timeout=300)
# timeout 默认300s

欢迎 fork 并提交您的优化代码

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/getcomputerstyle/article/details/103014896

智能推荐

c# 调用c++ lib静态库_c#调用lib-程序员宅基地

文章浏览阅读2w次,点赞7次,收藏51次。四个步骤1.创建C++ Win32项目动态库dll 2.在Win32项目动态库中添加 外部依赖项 lib头文件和lib库3.导出C接口4.c#调用c++动态库开始你的表演...①创建一个空白的解决方案,在解决方案中添加 Visual C++ , Win32 项目空白解决方案的创建:添加Visual C++ , Win32 项目这......_c#调用lib

deepin/ubuntu安装苹方字体-程序员宅基地

文章浏览阅读4.6k次。苹方字体是苹果系统上的黑体,挺好看的。注重颜值的网站都会使用,例如知乎:font-family: -apple-system, BlinkMacSystemFont, Helvetica Neue, PingFang SC, Microsoft YaHei, Source Han Sans SC, Noto Sans CJK SC, W..._ubuntu pingfang

html表单常见操作汇总_html表单的处理程序有那些-程序员宅基地

文章浏览阅读159次。表单表单概述表单标签表单域按钮控件demo表单标签表单标签基本语法结构<form action="处理数据程序的url地址“ method=”get|post“ name="表单名称”></form><!--action,当提交表单时,向何处发送表单中的数据,地址可以是相对地址也可以是绝对地址--><!--method将表单中的数据传送给服务器处理,get方式直接显示在url地址中,数据可以被缓存,且长度有限制;而post方式数据隐藏传输,_html表单的处理程序有那些

PHP设置谷歌验证器(Google Authenticator)实现操作二步验证_php otp 验证器-程序员宅基地

文章浏览阅读1.2k次。使用说明:开启Google的登陆二步验证(即Google Authenticator服务)后用户登陆时需要输入额外由手机客户端生成的一次性密码。实现Google Authenticator功能需要服务器端和客户端的支持。服务器端负责密钥的生成、验证一次性密码是否正确。客户端记录密钥后生成一次性密码。下载谷歌验证类库文件放到项目合适位置(我这边放在项目Vender下面)https://github.com/PHPGangsta/GoogleAuthenticatorPHP代码示例://引入谷_php otp 验证器

【Python】matplotlib.plot画图横坐标混乱及间隔处理_matplotlib更改横轴间距-程序员宅基地

文章浏览阅读4.3k次,点赞5次,收藏11次。matplotlib.plot画图横坐标混乱及间隔处理_matplotlib更改横轴间距

docker — 容器存储_docker 保存容器-程序员宅基地

文章浏览阅读2.2k次。①Storage driver 处理各镜像层及容器层的处理细节,实现了多层数据的堆叠,为用户 提供了多层数据合并后的统一视图②所有 Storage driver 都使用可堆叠图像层和写时复制(CoW)策略③docker info 命令可查看当系统上的 storage driver主要用于测试目的,不建议用于生成环境。_docker 保存容器

随便推点

网络拓扑结构_网络拓扑csdn-程序员宅基地

文章浏览阅读834次,点赞27次,收藏13次。网络拓扑结构是指计算机网络中各组件(如计算机、服务器、打印机、路由器、交换机等设备)及其连接线路在物理布局或逻辑构型上的排列形式。这种布局不仅描述了设备间的实际物理连接方式,也决定了数据在网络中流动的路径和方式。不同的网络拓扑结构影响着网络的性能、可靠性、可扩展性及管理维护的难易程度。_网络拓扑csdn

JS重写Date函数,兼容IOS系统_date.prototype 将所有 ios-程序员宅基地

文章浏览阅读1.8k次,点赞5次,收藏8次。IOS系统Date的坑要创建一个指定时间的new Date对象时,通常的做法是:new Date("2020-09-21 11:11:00")这行代码在 PC 端和安卓端都是正常的,而在 iOS 端则会提示 Invalid Date 无效日期。在IOS年月日中间的横岗许换成斜杠,也就是new Date("2020/09/21 11:11:00")通常为了兼容IOS的这个坑,需要做一些额外的特殊处理,笔者在开发的时候经常会忘了兼容IOS系统。所以就想试着重写Date函数,一劳永逸,避免每次ne_date.prototype 将所有 ios

如何将EXCEL表导入plsql数据库中-程序员宅基地

文章浏览阅读5.3k次。方法一:用PLSQL Developer工具。 1 在PLSQL Developer的sql window里输入select * from test for update; 2 按F8执行 3 打开锁, 再按一下加号. 鼠标点到第一列的列头,使全列成选中状态,然后粘贴,最后commit提交即可。(前提..._excel导入pl/sql

Git常用命令速查手册-程序员宅基地

文章浏览阅读83次。Git常用命令速查手册1、初始化仓库git init2、将文件添加到仓库git add 文件名 # 将工作区的某个文件添加到暂存区 git add -u # 添加所有被tracked文件中被修改或删除的文件信息到暂存区,不处理untracked的文件git add -A # 添加所有被tracked文件中被修改或删除的文件信息到暂存区,包括untracked的文件...

分享119个ASP.NET源码总有一个是你想要的_千博二手车源码v2023 build 1120-程序员宅基地

文章浏览阅读202次。分享119个ASP.NET源码总有一个是你想要的_千博二手车源码v2023 build 1120

【C++缺省函数】 空类默认产生的6个类成员函数_空类默认产生哪些类成员函数-程序员宅基地

文章浏览阅读1.8k次。版权声明:转载请注明出处 http://blog.csdn.net/irean_lau。目录(?)[+]1、缺省构造函数。2、缺省拷贝构造函数。3、 缺省析构函数。4、缺省赋值运算符。5、缺省取址运算符。6、 缺省取址运算符 const。[cpp] view plain copy_空类默认产生哪些类成员函数

推荐文章

热门文章

相关标签