You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Python Requests请求含Emoji的URL时解码失败问题求助

含Emoji/特殊字符的URL在requests中请求失败的解决办法

我用Python的requests模块发起请求时遇到编码问题,代码如下:

import requests
url = "https://www.foo.bar/topic/512174-some-text-�-text-some-�☀️/"
r=requests.get(url)

试过Python 3.11.0、3.7.3,requests 2.30.0、2.25.1版本,目标论坛的原始URL格式类似:https://www.foo.bar/topic/1234567-✅-some-text-✅/

已尝试的方案

  • 方案1:直接传入URL时触发编码错误:'utf-8' codec can't decode bytes in position 35-37: invalid continuation byte,请求无法执行
  • 方案2:从网页源码获取URL后用utf-8解码,得到的URL是https://www.foo.bar/topic/1234567-�-some-text-��/,请求依然失败
  • 方案3:改用latin-1编码解码URL,还是无法处理特殊字符
  • 方案4:用urllib的quote方法转义URL字符,转义结果和浏览器处理方式不一致,请求失败

使用的请求头:

headers = {
    "Accept": "text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8",
    "Accept-Language": "en-US,en;q=0.5",
    "Accept-Encoding": "gzip,deflate",
    "Connection": "keep-alive",
    "Upgrade-Insecure-Requests": "1",
}

补充:Requests能正常处理已百分编码的Emoji,但从原始HTML拿到的URL如www.foo.bar/topic/123123-some-text-�--text-some-�☀️/,用urllib.quote转义后得到https://www.foo.bar/topic/1233123-some-text-%EF%BF%BD-text-some-%EF%BF%BD%E2%98%80%EF%B8%8F,请求还是失败,怀疑是新Emoji的编码问题导致。

可行解决方案

1. 确保URL的原始字节正确解码

从网页源码获取URL时,不要盲目用utf-8或latin-1解码,先确认网页的实际编码(比如从响应的Content-Type头获取,或者用chardet/cchardet自动检测),再用对应编码解码:

import requests
from chardet import detect

# 先获取网页源码的原始字节
response = requests.get("论坛首页URL")
encoding = detect(response.content)['encoding']
# 用正确编码解码HTML
html = response.content.decode(encoding)
# 从解码后的HTML中提取URL

2. 手动构造符合网站规则的URL

观察论坛URL格式:https://www.foo.bar/topic/[ID]-[Emoji]-[文本]-[Emoji]/,可以提取帖子ID和文本部分,再手动替换成正确的Emoji编码(参考浏览器地址栏的编码结果)。比如浏览器中✅的编码是%E2%9C%85,直接用这个构造URL:

url = "https://www.foo.bar/topic/512174-some-text-%E2%9C%85-text-some-%E2%9C%85%E2%98%80%EF%B8%8F/"
r = requests.get(url, headers=headers)

3. 使用requests的预编码URL方式

把URL拆分成scheme、netloc、path等部分,用urllib.parse.urlunparse拼接,确保path部分正确编码:

from urllib.parse import urlunparse, quote

url_parts = (
    "https",
    "www.foo.bar",
    "/topic/512174-some-text-✅-text-some-✅☀️/",
    "",
    "",
    ""
)
# 单独对path部分编码,保留/不被转义
encoded_path = quote(url_parts[2], safe='/')
url_parts = url_parts[:2] + (encoded_path,) + url_parts[3:]
final_url = urlunparse(url_parts)
r = requests.get(final_url, headers=headers)

4. 直接使用原始字节发起请求

绕过字符串解码的问题,直接用字节形式的URL请求(requests支持传入字节对象作为URL):

# 假设从网页源码中获取到的原始字节URL是url_bytes
url_bytes = b"https://www.foo.bar/topic/512174-some-text-\xe2\x9c\x85-text-some-\xe2\x9c\x85\xe2\x98\x80\xef\xb8\x8f/"
r = requests.get(url_bytes, headers=headers)

内容的提问来源于stack exchange,提问作者emilio-cea

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.22 07:52:46