httpx 快速入门
首先,从导入 HTTPX 开始:
>>> import httpx
现在,让我们尝试获取一个网页。
>>> r = httpx.get('https://httpbin.org/get')
>>> r
<Response [200 OK]>
同样,要发出 HTTP POST 请求:
>>> r = httpx.post('https://httpbin.org/post', data={'key': 'value'})
PUT、DELETE、HEAD 和 OPTIONS 请求都遵循相同的样式:
>>> 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')
在 URL 中传递参数
要在请求中包含 URL 查询参数,请使用关键字:params
>>> params = {'key1': 'value1', 'key2': 'value2'}
>>> r = httpx.get('https://httpbin.org/get', params=params)
要查看值如何编码到 URL 字符串中,我们可以检查用于发出请求的结果 URL:
>>> r.url
URL('https://httpbin.org/get?key2=value2&key1=value1')
您还可以将项目列表作为值传递:
>>> params = {'key1': 'value1', 'key2': ['value2', 'value3']}
>>> r = httpx.get('https://httpbin.org/get', params=params)
>>> r.url
URL('https://httpbin.org/get?key1=value1&key2=value2&key2=value3')
响应内容
HTTPX 将自动处理将响应内容解码为 Unicode 文本的过程。
>>> r = httpx.get('https://www.example.org/')
>>> r.text
'<!doctype html>\n<html>\n<head>\n<title>Example Domain</title>...'
您可以检查将用于解码响应的编码。
>>> r.encoding
'UTF-8'
在某些情况下,响应可能不包含显式编码,在这种情况下,HTTPX 将尝试自动确定要使用的编码。
>>> r.encoding
None
>>> r.text
'<!doctype html>\n<html>\n<head>\n<title>Example Domain</title>...'
如果您需要覆盖标准行为并显式设置要使用的编码,那么您也可以这样做。
>>> r.encoding = 'ISO-8859-1'
二进制响应内容
对于非文本响应,响应内容也能以字节的形式进行访问:
>>> r.content
b'<!doctype html>\n<html>\n<head>\n<title>Example Domain</title>...'
任何gzip
和deflate
HTTP响应编码都将自动为您解码。如果安装了brotli
,则也将支持brotli
响应编码。
例如,要根据请求返回的二进制数据创建图片,可以使用以下代码:
>>> from PIL import Image
>>> from io import BytesIO
>>> i = Image.open(BytesIO(r.content))
JSON 响应内容
通常,Web API 响应将编码为 JSON。
>>> r = httpx.get('https://api.github.com/events')
>>> r.json()
[{u'repository': {u'open_issues': 0, u'url': 'https://github.com/...' ... }}]
自定义headers
要在传出请求中包含其他headers
,请使用关键字参数:headers
>>> url = 'https://httpbin.org/headers'
>>> headers = {'user-agent': 'my-app/0.0.1'}
>>> r = httpx.get(url, headers=headers)
发送表单编码数据
某些类型的 HTTP 请求(如 POST
和PUT
请求)可以在请求正文中包含数据。包含它的一种常见方法是作为表单编码的数据,用于HTML表单。
>>> data = {'key1': 'value1', 'key2': 'value2'}
>>> r = httpx.post("https://httpbin.org/post", data=data)
>>> print(r.text)
{
...
"form": {
"key2": "value2",
"key1": "value1"
},
...
}
表单编码数据还可以包含来自给定键的多个值。
>>> data = {'key1': ['value1', 'value2']}
>>> r = httpx.post("https://httpbin.org/post", data=data)
>>> print(r.text)
{
...
"form": {
"key1": [
"value1",
"value2"
]
},
...
}
发送分段文件上传
您还可以使用 HTTP 分段编码上传文件:
>>> files = {'upload-file': open('report.xls', 'rb')}
>>> r = httpx.post("https://httpbin.org/post", files=files)
>>> print(r.text)
{
...
"files": {
"upload-file": "<... binary content ...>"
},
...
}
还可以通过使用项的元组作为文件值来显式设置文件名和内容类型:
>>> files = {'upload-file': ('report.xls', open('report.xls', 'rb'), 'application/vnd.ms-excel')}
>>> r = httpx.post("https://httpbin.org/post", files=files)
>>> print(r.text)
{
...
"files": {
"upload-file": "<... binary content ...>"
},
...
}
如果需要在多部分表单中包含非文件数据字段,请使用以下参数:
data=
...
>>> data = {'message': 'Hello, world!'}
>>> files = {'file': open('report.xls', 'rb')}
>>> r = httpx.post("https://httpbin.org/post", data=data, files=files)
>>> print(r.text)
{
...
"files": {
"file": "<... binary content ...>"
},
"form": {
"message": "Hello, world!",
},
...
}
发送 JSON 编码数据
如果您只需要一个简单的键值数据结构,则表单编码数据是可以的。对于更复杂的数据结构,您通常需要改用 JSON 编码。
>>> data = {'integer': 123, 'boolean': True, 'list': ['a', 'b', 'c']}
>>> r = httpx.post("https://httpbin.org/post", json=data)
>>> print(r.text)
{
...
"json": {
"boolean": true,
"integer": 123,
"list": [
"a",
"b",
"c"
]
},
...
}
发送二进制请求数据
对于其他编码,应该使用content=...
参数,传递bytes
类型或生成bytes
的生成器。
>>> content = b'Hello, world'
>>> r = httpx.post("https://httpbin.org/post", content=content)
您可能还希望在上传二进制数据时设置自定义标头Content-Type
。
响应状态代码
我们可以检查响应的 HTTP 状态代码:
>>> r = httpx.get('https://httpbin.org/get')
>>> r.status_code
200
HTTPX还包括一个简单的快捷方式,用于通过文本短语访问状态代码。
>>> r.status_code == httpx.codes.OK
True
我们可以为任何不是 2xx
成功代码的响应提出异常:
>>> not_found = httpx.get('https://httpbin.org/status/404')
>>> not_found.status_code
404
>>> not_found.raise_for_status()
Traceback (most recent call last):
File "/Users/tomchristie/GitHub/encode/httpcore/httpx/models.py", line 837, in raise_for_status
raise HTTPStatusError(message, response=self)
httpx._exceptions.HTTPStatusError: 404 Client Error: Not Found for url: https://httpbin.org/status/404
For more information check: https://httpstatuses.com/404
任何成功的响应代码将只是返回None
,而不是引发异常。
>>> r.raise_for_status()
响应标头
响应标头可用作类似字典的接口。
>>> r.headers
Headers({
'content-encoding': 'gzip',
'transfer-encoding': 'chunked',
'connection': 'close',
'server': 'nginx/1.0.4',
'x-runtime': '148ms',
'etag': '"e1ca502697e5c9317743dc078f67693f"',
'content-type': 'application/json'
})
数据类型不区分大小写,因此Headers
可以使用任意大小写(大小写不敏感)。
>>> r.headers['Content-Type']
'application/json'
>>> r.headers.get('content-type')
'application/json'
根据 RFC 7230,单个响应标头的多个值表示为单个逗号分隔值:
收件人可以将具有相同字段名称的多个标头字段组合成一个“字段名称:字段值”对,而无需更改消息的语义,方法是按顺序将每个后续字段值附加到组合的字段值中,并用逗号分隔。
流式处理响应
对于大型下载,您可能希望使用不会一次将整个响应正文加载到内存中的流式处理响应。
您可以流式传输响应的二进制内容...
>>> with httpx.stream("GET", "https://www.example.com") as r:
... for data in r.iter_bytes():
... print(data)
或者回复的文本...
>>> with httpx.stream("GET", "https://www.example.com") as r:
... for text in r.iter_text():
... print(text)
或者逐行流式传输文本...
>>> with httpx.stream("GET", "https://www.example.com") as r:
... for line in r.iter_lines():
... print(line)
HTTPX 将使用通用行尾,将所有情况规范化为 \n
。
在某些情况下,您可能希望在不应用任何 HTTP 内容解码的情况下访问响应上的原始字节。在这种情况下,Web 服务器已应用的任何内容编码,如 gzip
、deflate
或 brotli
都不会自动解码。
>>> with httpx.stream("GET", "https://www.example.com") as r:
... for chunk in r.iter_raw():
... print(chunk)
如果以上述任何一种方式使用流式处理响应,则 response.content
和response.text
属性将不可用,并且在访问时将引发错误。但是,您也可以使用响应流式处理功能有条件地加载响应正文:
>>> with httpx.stream("GET", "https://www.example.com") as r:
... if r.headers['Content-Length'] < TOO_LONG:
... r.read()
... print(r.text)
Cookie
可以轻松访问在响应中设置的任何 Cookie:
>>> r = httpx.get('https://httpbin.org/cookies/set?chocolate=chip')
>>> r.cookies['chocolate']
'chip'
要在传出请求中包含 Cookie,请使用以下参数:cookies
>>> cookies = {"peanut": "butter"}
>>> r = httpx.get('https://httpbin.org/cookies', cookies=cookies)
>>> r.json()
{'cookies': {'peanut': 'butter'}}
Cookies在Cookies
实例中返回,该实例是一种类似字典的数据结构,具有用于按域或路径访问 Cookie 的附加 API。
>>> cookies = httpx.Cookies()
>>> cookies.set('cookie_on_domain', 'hello, there!', domain='httpbin.org')
>>> cookies.set('cookie_off_domain', 'nope.', domain='example.org')
>>> r = httpx.get('http://httpbin.org/cookies', cookies=cookies)
>>> r.json()
{'cookies': {'cookie_on_domain': 'hello, there!'}}
重定向和历史记录
默认情况下,HTTPX 不会遵循所有 HTTP 方法的重定向,尽管可以显式启用此功能。
例如,GitHub 将所有 HTTP 请求重定向到 HTTPS。
>>> r = httpx.get('http://github.com/')
>>> r.status_code
301
>>> r.history
[]
>>> r.next_request
<Request('GET', 'https://github.com/')>
您可以使用follow_redirects
参数修改默认重定向处理:
>>> r = httpx.get('http://github.com/', follow_redirects=True)
>>> r.url
URL('https://github.com/')
>>> r.status_code
200
>>> r.history
[<Response [301 Moved Permanently]>]
响应的history
属性可用于检查任何关注的重定向。它包含所遵循的任何重定向响应的列表,按其创建顺序排列。
超时
HTTPX 默认为所有网络操作包含合理的超时,这意味着如果连接未正确建立,则它应该始终引发错误,而不是无限期挂起。
网络不活动的默认超时为五秒。您可以将值修改为更严格:
>>> httpx.get('https://github.com/', timeout=0.001)
您还可以完全禁用超时行为...
>>> httpx.get('https://github.com/', timeout=None)
有关高级超时管理,请参阅超时设置。
认证
HTTPX 支持基本和摘要式 HTTP 身份验证。
要提供基本的身份验证凭据,请将一个2元组的纯文本str
或bytes
对象作为auth
参数传递给请求函数:
>>> httpx.get("https://example.com", auth=("my_user", "password123"))
要为摘要身份验证提供凭据,您需要实例化一个DigestAuth
对象,并将明文用户名和密码作为参数。然后,可以将该对象作为auth
参数传递给上述请求方法:
>>> auth = httpx.DigestAuth("my_user", "password123")
>>> httpx.get("https://example.com", auth=auth)
<Response [200 OK]>