Pythonurllib3教程介绍了Pythonurllib3模块。我们展示了如何抓取数据、发布数据、流式传输数据、使用JSON以及使用重定向。
ZetCode还有一个简明的Python教程。
超文本传输协议(HTTP)是分布式、协作、超媒体信息系统的应用协议。HTTP是万维网数据通信的基础。
Pythonurllib3
urllib3模块是一个强大的、对Python友好的HTTP客户端。它支持线程安全、连接池、客户端SSL/TLS验证、使用多部分编码的文件上传、重试请求和处理HTTP重定向的帮助程序、gzip和deflate编码以及HTTP和SOCKS的代理。
$ pip install urllib3
我们使用pip安装urllib3模块。
Pythonurllib3版本
第一个程序打印urllib3模块的版本。
#!/usr/bin/python import urllib3 print(urllib3.__version__)
程序打印版本或urllib3。
$ ./version.py 1.24.1
这是示例的示例输出。
Pythonurllib3状态
HTTP响应状态代码指示特定HTTP请求是否已成功完成。响应分为五类:
- 信息响应(100-199)
- 成功响应(200-299)
- 重定向(300-399)
- 客户端错误(400-499)
- 服务器错误(500-599)
#!/usr/bin/python
import urllib3
http = urllib3.PoolManager()
url = 'http://webcode.me'
resp = http.request('GET', url)
print(resp.status)
该示例创建了对webcode.me的GET请求。它打印响应的状态代码。
http = urllib3.PoolManager()
我们创建一个PoolManager来生成请求。它处理连接池和线程安全的所有细节。
url = 'http://webcode.me'
这是我们向其发送请求的URL。
resp = http.request('GET', url)
使用request方法,我们向指定的URL发出GET请求。
print(resp.status)
我们打印响应的状态代码。
$ status.py 200
200状态码代表请求成功
Pythonurllib3GET请求
HTTPGET方法请求指定资源的表示。
#!/usr/bin/python
import urllib3
http = urllib3.PoolManager()
url = 'http://webcode.me'
resp = http.request('GET', url)
print(resp.data.decode('utf-8'))
该示例向webcode.me网页发送GET请求。它返回主页的HTML代码。
req = http.request('GET', url)
生成GET请求。
print(resp.data.decode('utf-8'))
我们获取数据或响应并将其解码为文本。
$ ./get_request.py
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>My html page</title>
</head>
<body>
<p>
Today is a beautiful day. We go swimming and fishing.
</p>
<p>
Hello there. How are you?
</p>
</body>
Pythonurllib3HEAD请求
HEAD请求是没有消息正文的GET请求。
#!/usr/bin/python
import urllib3
http = urllib3.PoolManager()
url = 'http://webcode.me'
resp = http.request('HEAD', url)
print(resp.headers['Server'])
print(resp.headers['Date'])
print(resp.headers['Content-Type'])
print(resp.headers['Last-Modified'])
在示例中,我们创建了一个HEAD请求到webcode.me网站。
print(resp.headers['Server']) print(resp.headers['Date']) print(resp.headers['Content-Type']) print(resp.headers['Last-Modified'])
响应对象包含headers字典,其中包含各种标头字段,例如服务器和日期。
$ ./head_request.py nginx/1.6.2 Thu, 20 Feb 2020 14:35:14 GMT text/html Sat, 20 Jul 2019 11:49:25 GMT
从输出中我们可以看出网站的web服务器是nginx,内容类型是HTML代码。
Pythonurllib3HTTPS请求
urllib3提供客户端TLS/SSL验证。为此,我们需要下载certifi模块。它是一个精心策划的根证书集合,用于在验证TLS主机身份的同时验证SSL证书的可信度。它已从Requests项目中提取。
$ pip install certifi
我们安装certifi。
import certifi print(certifi.where())
要引用已安装的证书颁发机构(CA)包,我们使用内置的where函数。
#!/usr/bin/python
import urllib3
import certifi
url = 'https://httpbin.org/anything'
http = urllib3.PoolManager(ca_certs=certifi.where())
resp = http.request('GET', url)
print(resp.status)
我们向https://httpbin.org/anything页面创建一个GET请求。
http = urllib3.PoolManager(ca_certs=certifi.where())
我们将根CA包传递给PoolManager。如果没有此CA捆绑包,请求将发出以下警告:InsecureRequestWarning:正在发出未经验证的HTTPS请求。强烈建议添加证书验证。。
Pythonurllib3查询参数
查询参数是统一资源定位器(URL)的一部分,它为指定的参数赋值。这是将数据发送到目标服务器的一种方式。
http://example.com/api/users?name=John%20Doe&occupation=gardener
查询参数在?特点。多个字段用&分隔。对特殊字符(例如空格)进行编码。在上面的字符串中,空格使用%20值进行编码。
#!/usr/bin/python
import urllib3
import certifi
http = urllib3.PoolManager(ca_certs=certifi.where())
payload = {'name': 'Peter', 'age': 23}
url = 'https://httpbin.org/get'
req = http.request('GET', url, fields=payload)
print(req.data.decode('utf-8'))
在示例中,我们将带有一些查询参数的GET请求发送到https://httpbin.org/get。该链接只是将一些数据返回给客户端,包括查询参数。该站点用于测试HTTP请求。
payload = {'name': 'Peter', 'age': 23}
这是要发送的负载。
req = http.request('GET', url, fields=payload)
查询参数使用fields选项指定。
$ ./query_params.py
{
"args": {
"age": "23",
"name": "Peter"
},
"headers": {
"Accept-Encoding": "identity",
"Host": "httpbin.org",
"X-Amzn-Trace-Id": "Root=1-5e4ea45f-c3c9c721c848f8f81a3129d8"
},
"origin": "188.167.251.9",
"url": "https://httpbin.org/get?name=Peter&age=23"
}
httpbin.org以JSON字符串响应,其中也包括我们的有效负载。
Pythonurllib3POST请求
HTTPPOST方法向服务器发送数据。它通常在上传文件或提交完整的网络表单时使用。
#!/usr/bin/python
import urllib3
import certifi
http = urllib3.PoolManager(ca_certs=certifi.where())
url = 'https://httpbin.org/post'
req = http.request('POST', url, fields={'name': 'John Doe'})
print(req.data.decode('utf-8'))
该示例发送一个POST请求。数据使用fields选项指定。
$ ./post_request.py
{
"args": {},
"data": "",
"files": {},
"form": {
"name": "John Doe"
},
...
"url": "https://httpbin.org/post"
}
Pythonurllib3发送JSON
在POST或PUT等请求中,客户端通过Content-Type标头告诉服务器实际发送的数据类型。
#!/usr/bin/python
import urllib3
import certifi
import json
http = urllib3.PoolManager(ca_certs=certifi.where())
payload = {'name': 'John Doe'}
encoded_data = json.dumps(payload).encode('utf-8')
resp = http.request(
'POST',
'https://httpbin.org/post',
body=encoded_data,
headers={'Content-Type': 'application/json'})
data = json.loads(resp.data.decode('utf-8'))['json']
print(data)
该示例发送JSON数据。
payload = {'name': 'John Doe'}
encoded_data = json.dumps(payload).encode('utf-8')
我们将JSON数据编码为二进制格式。
resp = http.request(
'POST',
'https://httpbin.org/post',
body=encoded_data,
headers={'Content-Type': 'application/json'})
我们在请求中指定Content-Type标头。
data = json.loads(resp.data.decode('utf-8'))['json']
print(data)
我们将返回的数据解码回文本并将其打印到控制台。
Pythonurllib3二进制数据
在下面的例子中,我们下载二进制数据。
#!/usr/bin/python
import urllib3
http = urllib3.PoolManager()
url = 'http://webcode.me/favicon.ico'
req = http.request('GET', url)
with open('favicon.ico', 'wb') as f:
f.write(req.data)
该示例下载一个小图标。
with open('favicon.ico', 'wb') as f:
f.write(req.data)
req.data是二进制格式,我们可以直接写入磁盘。
Pythonurllib3流数据
分块传输编码是自HTTP1.1以来可用的流式数据传输机制。在分块传输编码中,数据流被分成一系列不重叠的块。
块是相互独立发送和接收的。每个块前面都有其大小(以字节为单位)。
将preload_content设置为False意味着urllib3将流式传输响应内容。stream方法迭代响应内容的块。流式传输时,我们应该调用release_conn将http连接释放回连接池,以便重新使用。
#!/usr/bin/python
import urllib3
import certifi
url = "https://docs.oracle.com/javase/specs/jls/se8/jls8.pdf"
local_filename = url.split('/')[-1]
http = urllib3.PoolManager(ca_certs=certifi.where())
resp = http.request(
'GET',
url,
preload_content=False)
with open(local_filename, 'wb') as f:
for chunk in resp.stream(1024):
f.write(chunk)
resp.release_conn()
在示例中,我们下载一个PDF文件。
resp = http.request(
'GET',
url,
preload_content=False)
使用preload_content=False,我们启用流式传输。
with open(local_filename, 'wb') as f:
for chunk in resp.stream(1024):
f.write(chunk)
我们迭代数据块并将它们保存到文件中。
resp.release_conn()
最后,我们释放连接。
Pythonurllib3重定向
重定向将用户和搜索引擎发送到与他们最初请求的不同的URL。为了遵循重定向,我们将redirect选项设置为True。
#!/usr/bin/python
import urllib3
import certifi
http = urllib3.PoolManager(ca_certs=certifi.where())
url = 'https://httpbin.org/redirect-to?url=/'
resp = http.request('GET', url, redirect=True)
print(resp.status)
print(resp.geturl())
print(resp.info())
该示例遵循重定向。
$ ./redirect.py
200
/
HTTPHeaderDict({'Date': 'Fri, 21 Feb 2020 12:49:29 GMT', 'Content-Type': 'text/html;
charset=utf-8', 'Content-Length': '9593', 'Connection': 'keep-alive',
'Server': 'gunicorn/19.9.0', 'Access-Control-Allow-Origin': '*',
'Access-Control-Allow-Credentials': 'true'})
Pythonurllib3Flask示例
在以下示例中,我们向小型FlaskWeb应用程序发送请求。在PythonFlask教程中了解有关FlaskWeb框架的更多信息。
$ pip install flask
我们需要安装flask模块。
#!/usr/bin/python
from flask import Flask
from flask import request
app = Flask(__name__)
@app.route('/headers')
def hello():
ua = request.headers.get('user-agent')
ka = request.headers.get('connection')
return f'User agent: {ua}; Connection: {ka}'
应用程序只有一个路由。它将请求的用户代理和连接标头字段发送到客户端。
#!/usr/bin/python
import urllib3
http = urllib3.PoolManager()
url = 'localhost:5000/headers'
headers = urllib3.make_headers(keep_alive=True, user_agent='Python program')
resp = http.request('GET', url, headers=headers)
print(resp.data.decode('utf-8'))
在此程序中,我们向Flask应用程序发送请求。
url = 'localhost:5000/headers'
默认情况下,Flask在端口5000上运行。
headers = urllib3.make_headers(keep_alive=True, user_agent='Python program')
使用make_headers辅助方法,我们创建了一个headers字典。
resp = http.request('GET', url, headers=headers)
我们向URL发送GET请求;我们指定标题字典。
print(resp.data.decode('utf-8'))
我们将响应打印到终端。
$ export FLASK_APP=app.py $ flask run
我们运行Flask应用程序。
$ ./send_req.py User agent: Python program; Connection: keep-alive
从不同的终端,我们启动send_req.py程序。
在本教程中,我们使用了Pythonurllib3模块。
列出所有Python教程。
