pin_drop当前位置:知识文库 ❯ 图文
Python urllib详解 - HTTP请求标准库实战教程
目录
一、urllib 概述
urllib 是 Python 标准库中用于处理 URL 的模块集合。它是 Python 内置的 HTTP 客户端,无需额外安装任何第三方包即可发起网络请求。
urllib 包含多个子模块:
-
urllib.request:用于打开和读取 URL
-
urllib.parse:用于解析 URL
-
urllib.error:包含请求可能抛出的异常
-
urllib.robotparser:用于解析 robots.txt 文件
小贴士
虽然 requests 库在第三方库中更为流行,但 urllib 作为标准库无需安装,在一些受限环境(如无法使用 pip 的服务器)中非常有用。Python 3 中将 urllib2 合并到了 urllib 模块中。
二、urlopen 基本用法
最简单的 GET 请求
urllib.request.urlopen() 是发起 HTTP 请求的核心函数,它支持 URL 字符串或 Request 对象作为参数:
代码示例
from urllib.request import urlopen
# 最简单的 GET 请求
response = urlopen('https://httpbin.org/get')
# 读取响应内容(返回 bytes)
html = response.read()
print(html.decode('utf-8'))
# 查看状态码
print(f'状态码: {response.status}')
# 查看响应头
print(f'Content-Type: {response.headers["Content-Type"]}')
# 关闭响应
response.close()使用 with 语句管理响应
代码示例
from urllib.request import urlopen
# 推荐:使用 with 语句自动关闭响应
with urlopen('https://httpbin.org/get') as response:
data = response.read()
print(f'状态码: {response.status}')
print(data.decode('utf-8'))读取响应内容
代码示例
from urllib.request import urlopen
import json
with urlopen('https://httpbin.org/get') as response:
# 方式1:一次性读取全部内容
all_content = response.read()
# 方式2:逐行读取
response2 = urlopen('https://httpbin.org/get')
for line in response2:
print(line.decode('utf-8').strip())
response2.close()
# 方式3:读取指定字节数
response3 = urlopen('https://httpbin.org/get')
chunk = response3.read(1024) # 只读取前 1024 字节
response3.close()
# 解析 JSON 响应
response4 = urlopen('https://httpbin.org/get')
json_data = json.loads(response4.read().decode('utf-8'))
print(json_data['url'])
response4.close()设置超时时间
代码示例
from urllib.request import urlopen
import socket
# 设置超时时间为 10 秒
try:
response = urlopen('https://httpbin.org/delay/5', timeout=10)
print(response.read().decode('utf-8'))
except socket.timeout:
print('请求超时!')三、Request 对象
当需要自定义请求头、请求方法或传递数据时,应使用urllib.request.Request对象:
代码示例
from urllib.request import Request, urlopen
# 创建 Request 对象
url = 'https://httpbin.org/get'
req = Request(url)
# 发送请求
with urlopen(req) as response:
print(response.read().decode('utf-8'))使用 parse.urlencode 构建查询参数
代码示例
from urllib.request import urlopen
from urllib.parse import urlencode
# 构建查询参数
params = {
'q': 'Python教程',
'page': 1,
'type': 'article'
}
# urlencode 将字典转换为 URL 编码的查询字符串
# 结果:q=Python%E6%95%99%E7%A8%8B&page=1&type=article
query_string = urlencode(params)
url = f'https://httpbin.org/get?{query_string}'
print(f'完整URL: {url}')
with urlopen(url) as response:
data = response.read().decode('utf-8')
print(data)四、添加请求头
许多网站会检查请求头来判断是否为浏览器请求。通过设置 User-Agent 等请求头可以模拟浏览器访问:
代码示例
from urllib.request import Request, urlopen
url = 'https://httpbin.org/headers'
# 创建请求并添加请求头
req = Request(url)
req.add_header('User-Agent', 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36')
req.add_header('Accept', 'application/json')
req.add_header('Accept-Language', 'zh-CN,zh;q=0.9')
# 或者在创建时直接指定 headers 参数
headers = {
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64)',
'Accept': 'application/json',
'Referer': 'https://www.example.com/'
}
req2 = Request(url, headers=headers)
with urlopen(req2) as response:
print(response.read().decode('utf-8'))动态添加/修改请求头
代码示例
from urllib.request import Request, urlopen
req = Request('https://httpbin.org/headers')
# 添加请求头
req.add_header('X-Custom-Header', 'MyValue')
# 查看已设置的请求头
print(req.headers)
# 修改 User-Agent
req.add_header('User-Agent', 'MyApp/1.0')
with urlopen(req) as response:
print(response.read().decode('utf-8'))五、POST 请求
发送表单数据
发起 POST 请求时,需要将数据编码为字节串并传递给 Request 对象的data参数:
代码示例
from urllib.request import Request, urlopen
from urllib.parse import urlencode
url = 'https://httpbin.org/post'
# 表单数据
form_data = {
'username': 'test_user',
'password': 'secret123',
'action': 'login'
}
# 将字典编码为 application/x-www-form-urlencoded 格式
encoded_data = urlencode(form_data).encode('utf-8')
# 创建 POST 请求(传入 data 参数即为 POST)
req = Request(url, data=encoded_data)
# 发送请求
with urlopen(req) as response:
result = response.read().decode('utf-8')
print(result)发送 JSON 数据
代码示例
from urllib.request import Request, urlopen
import json
url = 'https://httpbin.org/post'
# JSON 数据
json_data = {
'name': '张三',
'age': 28,
'email': 'zhangsan@example.com'
}
# 将 JSON 数据编码为字节串
json_bytes = json.dumps(json_data).encode('utf-8')
# 创建请求并设置 Content-Type
req = Request(
url,
data=json_bytes,
headers={
'Content-Type': 'application/json',
'User-Agent': 'Mozilla/5.0'
}
)
with urlopen(req) as response:
result = json.loads(response.read().decode('utf-8'))
print(f'提交的数据: {result["json"]}')
print(f'Content-Type: {result["headers"]["Content-Type"]}')
指定请求方法
代码示例
from urllib.request import Request, urlopen
# 使用 method 参数指定 HTTP 方法
req = Request('https://httpbin.org/delete', method='DELETE')
with urlopen(req) as response:
print(f'DELETE 状态码: {response.status}')
# PUT 请求
put_data = b'{"key": "value"}'
req_put = Request(
'https://httpbin.org/put',
data=put_data,
headers={'Content-Type': 'application/json'},
method='PUT'
)
with urlopen(req_put) as response:
print(f'PUT 状态码: {response.status}')六、异常处理
网络请求过程中可能会遇到各种异常,如网络断开、服务器错误、URL 无效等。urllib 提供了完善的异常体系:
代码示例
from urllib.request import urlopen
from urllib.error import URLError, HTTPError
import socket
url = 'https://httpbin.org/status/404'
try:
with urlopen(url, timeout=5) as response:
print(f'状态码: {response.status}')
print(response.read().decode('utf-8'))
except HTTPError as e:
# HTTP 错误(4xx, 5xx)
print(f'HTTP 错误: {e.code} - {e.reason}')
# HTTPError 也有 read() 方法,可以读取错误响应体
error_body = e.read().decode('utf-8')
print(f'错误详情: {error_body}')
except URLError as e:
# URL 错误(网络不可达、DNS 解析失败等)
print(f'URL 错误: {e.reason}')
except socket.timeout:
# 超时错误
print('请求超时,请检查网络连接')
except Exception as e:
# 其他未知错误
print(f'未知错误: {e}')完整封装的 GET 请求函数
代码示例
from urllib.request import Request, urlopen
from urllib.error import URLError, HTTPError
import socket
import json
def safe_get(url, headers=None, timeout=10):
"""安全的 GET 请求封装"""
try:
req = Request(url, headers=headers or {})
with urlopen(req, timeout=timeout) as response:
return {
'status': response.status,
'headers': dict(response.headers),
'body': response.read().decode('utf-8')
}
except HTTPError as e:
return {'error': f'HTTP {e.code}: {e.reason}'}
except URLError as e:
return {'error': f'URL Error: {e.reason}'}
except socket.timeout:
return {'error': '请求超时'}
except Exception as e:
return {'error': str(e)}
# 使用示例
result = safe_get('https://httpbin.org/get')
if 'error' in result:
print(f'请求失败: {result["error"]}')
else:
print(f'请求成功,状态码: {result["status"]}')七、urllib 与 requests 对比
urllib 和 requests 是 Python 中发起 HTTP 请求的两种常用方式。它们各有优缺点,适用于不同的场景:
八、注意事项
注意1:始终设置 timeout 参数,防止程序在网络异常时永久阻塞。urlopen 默认没有超时限制。
注意2:POST 请求的 data 参数必须是 bytes 类型,使用
.encode('utf-8')进行编码。
注意3:使用 with 语句管理 urlopen 返回的响应对象,确保连接正确释放。也可以显式调用
response.close()。
注意4:处理中文 URL 参数时,务必使用
urllib.parse.urlencode()或quote()进行 URL 编码,否则可能导致请求失败。
九、小结与练习题
核心要点回顾
-
urlopen:发起 HTTP 请求的核心函数,支持 GET 和 POST
-
Request 对象:用于自定义请求头、请求方法和数据
-
urlencode:将字典编码为 URL 查询字符串或表单数据
-
异常处理:使用 HTTPError 和 URLError 捕获不同类型的错误
-
始终设置超时:防止程序在网络异常时无限等待
练习1
编写一个函数fetch_webpage(url),使用 urllib 获取指定网页的 HTML 内容。要求:设置 User-Agent 请求头、10 秒超时,并处理可能出现的 HTTPError 和 URLError。
练习2
编写一个工具函数post_json(url, data),使用 urllib 发送 JSON 格式的 POST 请求。函数应自动设置 Content-Type 为 application/json,并返回解析后的 JSON 响应或错误信息。
常见问题
urllib 和 requests 哪个更好用?
如果项目允许安装第三方库,requests 是更好的选择,API 更简洁、功能更完善。如果无法安装第三方库(如受限服务器环境),urllib 作为标准库是唯一选择。对于简单的 GET/POST 请求,urllib 完全够用;对于复杂的会话管理、文件上传等场景,requests 更加便捷。
如何处理中文 URL 参数?
使用urllib.parse.urlencode()自动处理中文编码。例如:urlencode({'q': 'Python教程'})会返回'q=Python%E6%95%99%E7%A8%8B'。
urllib 如何保持 Cookie?
需要使用http.cookiejar模块。创建 CookieJar 对象,配合urllib.request.HTTPCookieProcessor构建 opener,后续请求会自动携带 Cookie。或者使用 requests 的 Session 对象,自动管理 Cookie 更加方便。
urlopen 返回的是什么类型?
urlopen 返回一个http.client.HTTPResponse对象。它支持read()、readline()、readlines()等方法,以及status、headers、geturl()等属性。read() 返回的是 bytes 类型,需要 decode() 转换为字符串。
本文涉及AI创作
内容由AI创作,请仔细甄别