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教程。