Python中如何使用urllib.request读取带中文的URL地址?

比如像这样的地址用 urllib.request 获取时会报错
http://www.china.com/中文 /2847228.html
Python中如何使用urllib.request读取带中文的URL地址?

5 回复
import urllib.request
import urllib.parse

# 原始URL(包含中文)
url = "https://example.com/search?q=中文参数"

# 方法1:手动编码URL组件
def encode_url_manually(url):
    # 分割URL为基本部分和查询部分
    if '?' in url:
        base, query = url.split('?', 1)
        # 编码查询参数
        encoded_query = urllib.parse.quote(query, safe='=&?')
        return base + '?' + encoded_query
    else:
        return urllib.parse.quote(url, safe=':/')

# 方法2:使用urllib.parse.urlsplit和urlunsplit
def encode_url_components(url):
    parts = list(urllib.parse.urlsplit(url))
    # 编码路径和查询部分
    parts[2] = urllib.parse.quote(parts[2])  # 路径
    if parts[3]:  # 查询字符串
        query_pairs = []
        for pair in parts[3].split('&'):
            if '=' in pair:
                key, value = pair.split('=', 1)
                query_pairs.append(f"{urllib.parse.quote(key)}={urllib.parse.quote(value)}")
            else:
                query_pairs.append(urllib.parse.quote(pair))
        parts[3] = '&'.join(query_pairs)
    return urllib.parse.urlunsplit(parts)

# 测试两种方法
encoded_url1 = encode_url_manually(url)
encoded_url2 = encode_url_components(url)

print("原始URL:", url)
print("方法1编码后:", encoded_url1)
print("方法2编码后:", encoded_url2)

# 实际请求示例
try:
    # 使用编码后的URL发起请求
    req = urllib.request.Request(encoded_url1)
    with urllib.request.urlopen(req) as response:
        print("请求成功,状态码:", response.status)
except Exception as e:
    print("请求失败:", e)

核心要点:

  1. URL编码原理:URL中只能包含ASCII字符,中文等非ASCII字符需要转换为%xx格式的字节序列
  2. 关键函数
    • urllib.parse.quote():编码单个字符串组件
    • urllib.parse.quote_plus():类似quote,但空格会转为+号(适用于查询参数)
    • safe参数:指定哪些字符不编码(如:/?=&等URL保留字符)
  3. 编码范围:通常需要编码查询参数值,有时也需要编码路径中的中文
  4. 完整编码流程:先拆分URL组件,分别编码各部分,再重新组合

建议直接使用方法2的组件编码方式更可靠。

unicode 字符应该是要编码成类似%20%20 这样的东西

先把 url 给 encode 一下应该就可以了。

urllib.urlencode(url)

用 requests

urlencode
其实就是中文部分每个字节转义成%十六进制

详见 http://w3school.com.cn/jsref/jsref_encodeuri.asp

回到顶部