一、为什么需要 URL 编码
刚开始做爬虫的时候,经常遇到请求失败的情况。检查半天发现,原来是 URL 里的中文或特殊字符没有编码。浏览器会自动处理,但用代码请求时就需要手动处理了。
URL 只能包含 ASCII 字符集中的可打印字符。如果 URL 中包含中文、空格或其他特殊字符,就需要进行编码转换。
需要编码的字符
- 非 ASCII 字符(如中文)
- 保留字符(如空格、&、=)
- 不安全字符(如 <、>、")
二、编码原理
URL 编码(也叫百分号编码)的原理很简单:把字符转换成 % 加上两位十六进制数的形式。
2.1 编码规则
# 中文字符
你 -> %E4%BD%A0
好 -> %E5%A5%BD
# 特殊字符
空格 -> %20
& -> %26
= -> %3D
# ASCII 字符
A -> A(不需要编码)
a -> a(不需要编码)
2.2 编码过程
# 原始字符:你
# 1. 转为 UTF-8 字节:\xe4\xbd\xa0
# 2. 每个字节转为十六进制:E4 BD A0
# 3. 加上百分号:%E4%BD%A0
三、Python 实现
3.1 使用 urllib
from urllib.parse import quote, unquote, quote_plus, unquote_plus
# 编码
text = '你好 world'
encoded = quote(text)
print(f"quote: {encoded}")
# quote: %E4%BD%A0%E5%A5%BD%20world
# 解码
decoded = unquote(encoded)
print(f"unquote: {decoded}")
# unquote: 你好 world
3.2 quote vs quote_plus
text = 'a b+c'
# quote:空格编码为 %20
print(quote(text)) # a%20b+c
# quote_plus:空格编码为 +,+ 编码为 %2B
print(quote_plus(text)) # a+b%2Bc
3.3 编码查询参数
from urllib.parse import urlencode
params = {
'name': '张三',
'age': 25,
'keyword': 'Python 爬虫'
}
# 自动编码参数
query_string = urlencode(params)
print(query_string)
# name=%E5%BC%A0%E4%B8%89&age=25&keyword=Python+%E7%88%AC%E8%99%AB
3.4 解析查询参数
from urllib.parse import parse_qs, urlparse
url = 'https://example.com/search?name=%E5%BC%A0%E4%B8%89&age=25'
# 解析 URL
parsed = urlparse(url)
print(f"路径: {parsed.path}")
print(f"查询: {parsed.query}")
# 解析参数
params = parse_qs(parsed.query)
print(params)
# {'name': ['张三'], 'age': ['25']}
四、常见场景
4.1 构造带参数的 URL
from urllib.parse import urlencode
base_url = 'https://api.example.com/search'
params = {
'keyword': 'Python 教程',
'page': 1,
'size': 20
}
# 构造完整 URL
url = f"{base_url}?{urlencode(params)}"
print(url)
# https://api.example.com/search?keyword=Python+%E6%95%99%E7%A8%8B&page=1&size=20
4.2 处理已编码的 URL
from urllib.parse import unquote
# 已编码的 URL
encoded_url = 'https://example.com/search?keyword=%E7%88%AC%E8%99%AB'
# 解码查看
decoded = unquote(encoded_url)
print(decoded)
# https://example.com/search?keyword=爬虫
4.3 编码路径
from urllib.parse import quote
# 路径中的中文
path = '/用户/张三/文档'
encoded_path = quote(path, safe='/')
print(encoded_path)
# /%E7%94%A8%E6%88%B7/%E5%BC%A0%E4%B8%89/%E6%96%87%E6%A1%A3
五、编码方式对比
| 方法 | 空格 | 中文 | 特殊字符 | 适用场景 |
|---|---|---|---|---|
| quote | %20 | 编码 | 编码 | URL 路径 |
| quote_plus | + | 编码 | 编码 | 查询参数 |
| urlencode | + | 编码 | 编码 | 构造查询字符串 |
六、总结
URL 编码是爬虫开发中的基础技能。记住这几个要点:
- URL 中的中文和特殊字符必须编码
- 路径用
quote,查询参数用urlencode - Requests 库会自动处理编码,但手动构造 URL 时要注意
- 遇到编码问题,先用
unquote查看原始内容