0%

http2的安装与使用教程

http2的安装与使用教程:

Mac下安装httpx:

报错:

场景:pip3 install httpx[http2] 当在Mac中执行此命令时出现 zsh: no matches found: httpx[http2]

注意:此问题适用于所有相关场景 zsh: no matches found: xxx

解决办法:

1、编辑 zprofile 文件

vim ~/.zprofile

2、在文件中添加 setopt no_nomatch,然后按ESC保存文件 :wq

setopt no_nomatch

3、重新执行文件

source ~/.zprofile

之后可以重新尝试执行命令。

httpx需要Python3.6+(使用异步请求需要Python3.8+)

pip3 install httpx

python3 -m pip install httpx

如果需要使用HTTP/2,则需要安装http2的相关依赖

pip3 install httpx[http2]
python3 -m pip install httpx[http2]

使用教程:

使用 httpx 来获取 HTTP/2 的内容时,可以配置 HTTP/2 支持并设置相关参数。httpx 是一个支持异步编程和 HTTP/2 协议的 Python 库,使用它可以轻松发出 HTTP/2 请求。

下面是一个示例代码,演示如何使用 httpx 来获取 HTTP/2 的内容:

同步使用(测试正常):

import httpx

# 创建一个支持 HTTP/2 的客户端
with httpx.Client(http2=True) as client:
url = "https://ev-h.phncdn.com/hls/videos/202309/29/440305311/720P_4000K_440305311.mp4/master.m3u8?validfrom=1730126962&validto=1730134162&ipa=35.241.118.11&hdl=-1&hash=e+p6Imk3TAqllNY8Os/rJvoWk+w="

# 发送 GET 请求
response = client.get(url)

# 检查响应状态码
if response.status_code == 200:
# 输出内容或将其保存到文件
with open("master.m3u8", "wb") as file:
file.write(response.content)
print("m3u8 文件下载成功")
else:
print(f"请求失败,状态码:{response.status_code}")

异步使用(测试正常):

如果想要异步执行请求,可以使用 httpx.AsyncClient,如下所示:

import httpx
import asyncio

async def fetch_m3u8():
url = "https://ev-h.phncdn.com/hls/videos/202309/29/440305311/720P_4000K_440305311.mp4/master.m3u8?validfrom=1730126962&validto=1730134162&ipa=35.241.118.11&hdl=-1&hash=e+p6Imk3TAqllNY8Os/rJvoWk+w="

# 使用 AsyncClient 创建一个支持 HTTP/2 的异步客户端
async with httpx.AsyncClient(http2=True) as client:
# 异步发送 GET 请求
response = await client.get(url)

# 检查响应状态码
if response.status_code == 200:
# 输出内容或将其保存到文件
with open("master.m3u8", "wb") as file:
file.write(response.content)
print("m3u8 文件下载成功")
else:
print(f"请求失败,状态码:{response.status_code}")

# 运行异步函数
asyncio.run(fetch_m3u8())

上述代码使用了 httpx 的 HTTP/2 支持功能,通过设置 http2=True 参数来启用。根据需要可以进一步添加自定义的请求头信息、超时设置、代理等参数。

简单使用

httpx与requests库的基本使用方法几乎是一模一样的

import httpx
r = httpx.get('https://httpbin.org/get')
print(r) # <Response [200 OK]>

类似的,我们也可以使用POST, PUT, DELETE, HEAD和OPTIONS等请求方法,如下

r = httpx.post('https://httpbin.org/post', data={'key': 'value'})
r = httpx.put('https://httpbin.org/put', data={'key': 'value'})
r = httpx.delete('https://httpbin.org/delete')
r = httpx.head('https://httpbin.org/get')
r = httpx.options('https://httpbin.org/get')

带有请求头和请求参数的请求

import httpx

headers = {'user-agent': 'my-app/1.0.0'}
params = {'key1': 'value1', 'key2': 'value2'}
url = 'https://httpbin.org/get'
r = httpx.get(url, headers=headers, params=params)
print(r)
print(r.status_code) # 状态码
print(r.encoding) # 文本编码
print(r.text)
print(r.json())

结果如下

<Response [200 OK]>
200
ascii
{
"args": {
"key1": "value1",
"key2": "value2"
},
"headers": {
"Accept": "*/*",
"Accept-Encoding": "gzip, deflate",
"Host": "httpbin.org",
"User-Agent": "my-app/1.0.0",
"X-Amzn-Trace-Id": "Root=1-6139b788-2fd67d5627a5f6de346e154a"
},
"origin": "113.110.227.200",
"url": "https://httpbin.org/get?key1=value1&key2=value2"
}

{'args': {'key1': 'value1', 'key2': 'value2'}, 'headers': {'Accept': '*/*', 'Accept-Encoding': 'gzip, deflate', 'Host': 'httpbin.org', 'User-Agent': 'my-app/1.0.0', 'X-Amzn-Trace-Id': 'Root=1-6139b788-2fd67d5627a5f6de346e154a'}, 'origin': '113.110.227.200', 'url': 'https://httpbin.org/get?key1=value1&key2=value2'}

请求带有cookies

import httpx

url = 'http://httpbin.org/cookies'
cookies = {'color': 'green'}
r = httpx.get(url, cookies=cookies)
print(r.json()) # {'cookies': {'color': 'green'}}

设置超时时间

import httpx

r = httpx.get('http://httpbin.org', timeout=0.001)
print(r)

超过设置时间则报httpx.ConnectTimeout: timed out

高级用法

我们使用上面的请求方式时,httpx每次发送请求都需要建立一个新的连接,然而随着请求的数量增加,整个程序的请求效率就会变得很低。

httpx提供了Client来解决以上问题,Client是基于HTTP连接池实现的,这意味着当你对一个网站发送多次请求的时候,Client会保持原有的TCP连接,从而提升程序的执行效率。

使用Client发送请求
创建一个client对象,使用该对象去做相应的请求

import httpx

with httpx.Client() as client:
headers = {'X-Custom': 'value'}
r = client.get('https://example.com', headers=headers)
print(r.text)

跨请求共享配置
我们可以将headers、cookies、params等参数放在http.Client()中,在Client下的请求共享这些配置参数

import httpx

headers1 = {'x-auth': 'from-client'}
params1 = {'client_id': '1234'}
url = 'https://example.com'
with httpx.Client(headers=headers1, params=params1) as client:
headers2 = {'x-custom': 'from-request'}
params2 = {'request_id': '4321'}
r1 = client.get(url)
print(r1.request.headers)
r2 = client.get(url, headers=headers2, params=params2)
print(r2.request.headers)

结果如下

Headers({'host': 'example.com', 'accept': '*/*', 'accept-encoding': 'gzip, deflate', 'connection': 'keep-alive', 'user-agent': 'python-httpx/0.19.0', 'x-auth': 'from-client'})
Headers({'host': 'example.com', 'accept': '*/*', 'accept-encoding': 'gzip, deflate', 'connection': 'keep-alive', 'user-agent': 'python-httpx/0.19.0', 'x-auth': 'from-client', 'x-custom': 'from-request'})

可以看出,r1的请求头包含{‘x-auth’: ‘from-client’}, r2虽然配置了headers2,但由于里面的headers1和headers2的参数不同,Client会合并这两个headers的参数作为一个新的headers(如果参数相同,则headers2的参数会覆盖headers1的参数)。

HTTP代理

httpx可以通过设置proxies参数来使用http代理,我们也可以使用不同的代理来分别处理http和https协议的请求,假设有如下两个代理

import httpx

proxies = {
'http://': 'http://localhost:8080', # 代理1
'https://': 'http://localhost:8081', # 代理2
}
url = 'https://example.com'
with httpx.Client(proxies=proxies) as client:
r1 = client.get(url)
print(r1)

上面的代理只是示范,实际场景下请替换成有效的ip代理

还有一点需要注意的是,httpx的代理参数proxies只能在httpx.Client()中添加,client.get()是没有这个参数的。

超时处理

默认情况下,httpx到处都做了严格的超时处理,默认时间为5秒,超过5秒无响应则报TimeoutException

普通请求:

httpx.get('http://example.com/api/v1/example', timeout=10.0)

client实例:

with httpx.Client() as client:
client.get("http://example.com/api/v1/example", timeout=10.0)

或者关闭超时处理

普通请求:

httpx.get('http://example.com/api/v1/example', timeout=None)

client实例:

with httpx.Client() as client:
client.get("http://example.com/api/v1/example", timeout=None)

SSL验证

当请求https协议的链接时,发出的请求需要验证所请求主机的身份,因此需要SSL证书来取得服务器的信任后。

如果要使用自定义的CA证书,则可以使用verify参数

import httpx

r = httpx.get("https://example.org", verify="path/to/client.pem")

或者你可以完全禁用SSL验证(不推荐)。

import httpx

r = httpx.get("https://example.org", verify=False)

异步支持
默认情况下,httpx使用标准的同步请求方式,如果需要的话,我们也可以使用它提供的异步client来发送相关请求。

使用异步client比使用多线程发送请求更加高效,更能体现明显的性能优势,并且它还支持WebSocket等长网络连接。

异步请求
使用async/await语句来进行异步操作,创建一个httpx.AsyncClient()对象

import asyncio
import httpx

async def main():
async with httpx.AsyncClient() as client: # 创建一个异步client
r = await client.get('https://www.example.com/')
print(r)


if __name__ == '__main__':
asyncio.run(main())

同步请求与异步请求的比较

我们来尝试使用同步和异步的方法进行请求,对比两种不同的方法的效率情况。

同步请求

import time
import httpx

def main():
with httpx.Client() as client:
for i in range(300):
res = client.get('https://www.example.com')
print(f'第{i + 1}次请求,status_code = {res.status_code}')


if __name__ == '__main__':
start = time.time()
main()
end = time.time()
print(f'同步发送300次请求,耗时:{end - start}')

同步发送300次请求,耗时:49.65340781211853

异步请求

import asyncio
import time
import httpx


async def req(client, i):
res = await client.get('https://www.example.com')
print(f'第{i + 1}次请求,status_code = {res.status_code}')
return res


async def main():
async with httpx.AsyncClient() as client:
task_list = [] # 任务列表
for i in range(300):
res = req(client, i)
task = asyncio.create_task(res) # 创建任务
task_list.append(task)
await asyncio.gather(*task_list) # 收集任务


if __name__ == '__main__':
start = time.time()
asyncio.run(main())
end = time.time()
print(f'异步发送300次请求,耗时:{end - start}')

异步发送300次请求,耗时:2.5227813720703125 (由于是异步执行的,所以打印的i值是无序的)

从两个例子可以看出,异步请求明显比同步请求的效率高很多。

以上就是httpx库的基本使用方法,想了解更多可以去 httpx官方文档中查看。