Python 中的 URL 解码 UTF-8
- 2025-01-07 08:44:00
- admin 原创
- 88
问题描述:
在 Python 2.7 中,给定一个类似这样的 URL:
example.com?title=%D0%BF%D1%80%D0%B0%D0%B2%D0%BE%D0%B2%D0%B0%D1%8F+%D0%B7%D0%B0%D1%89 %D0%B8%D1%82%D0%B0
我怎样才能将其解码为预期结果example.com?title==правовая+защита
?
我试过了url=urllib.unquote(url.encode("utf8"))
,但似乎给出了错误的结果。
解决方案 1:
数据是使用 URL 引用转义的 UTF-8 编码字节,因此您需要使用解码,urllib.parse.unquote()
它可以透明地处理从百分比编码数据到 UTF-8 字节再到文本的解码:
from urllib.parse import unquote
url = unquote(url)
演示:
>>> from urllib.parse import unquote
>>> url = 'example.com?title=%D0%BF%D1%80%D0%B0%D0%B2%D0%BE%D0%B2%D0%B0%D1%8F+%D0%B7%D0%B0%D1%89%D0%B8%D1%82%D0%B0'
>>> unquote(url)
'example.com?title=правовая+защита'
Python 2 的等效项是urllib.unquote()
,但这会返回一个字节串,因此您必须手动解码:
from urllib import unquote
url = unquote(url).decode('utf8')
解决方案 2:
如果你使用的是 Python 3,那么可以使用urllib.parse.unquote
:
url = """example.com?title=%D0%BF%D1%80%D0%B0%D0%B2%D0%BE%D0%B2%D0%B0%D1%8F+%D0%B7%D0%B0%D1%89%D0%B8%D1%82%D0%B0"""
import urllib.parse
urllib.parse.unquote(url)
给出:
'example.com?title=правовая+защита'
解决方案 3:
requests
您也可以使用库获得预期的结果:
import requests
url = "http://www.mywebsite.org/Data%20Set.zip"
print(f"Before: {url}")
print(f"After: {requests.utils.unquote(url)}")
输出:
$ python3 test_url_unquote.py
Before: http://www.mywebsite.org/Data%20Set.zip
After: http://www.mywebsite.org/Data Set.zip
如果您已经在使用requests
,这可能会很方便,而无需使用其他库来完成这项工作。
解决方案 4:
在 HTML 中,URL 可以包含 HTML 实体。这也会替换它们。
#from urllib import unquote #earlier python version
from urllib.request import unquote
from html import unescape
unescape(unquote('https://v.w.xy/p1/p22?userId=xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx&confirmationToken=7uAf%2fxJoxRTFAZdxslCn2uwVR9vV7cYrlHs%2fl9sU%2frix9f9CnVx8uUT%2bu8y1%2fWCs99INKDnfA2ayhGP1ZD0z%2bodXjK9xL5I4gjKR2xp7p8Sckvb04mddf%2fiG75QYiRevgqdMnvd9N5VZp2ksBc83lDg7%2fgxqIwktteSI9RA3Ux9VIiNxx%2fZLe9dZSHxRq9AA'))
解决方案 5:
我知道这是一个老问题,但我通过谷歌搜索偶然发现了这个问题,发现没有人提出仅具有内置功能的解决方案。
所以我很快就写了自己的。
基本上,url 字符串只能包含以下字符:AZ、az、0-9、-、.、_、~、:、/、?、#、[、]、@、!、$、&、'、(, )、*、+、,、;、% 和 =,其他所有字符都经过 url 编码。
URL 编码非常简单,只需一个百分号,后面跟着与非法字符的代码点相对应的字节值的十六进制数字。
因此,基本上使用一个简单的 while 循环来迭代字符,如果不是百分号,则按原样添加任何字符的字节,将索引增加一,否则添加百分号后的字节并将索引增加三,累积字节并对其进行解码应该可以完美工作。
以下是代码:
def url_parse(url):
l = len(url)
data = bytearray()
i = 0
while i < l:
if url[i] != '%':
d = ord(url[i])
i += 1
else:
d = int(url[i+1:i+3], 16)
i += 3
data.append(d)
return data.decode('utf8')
我已经测试过了并且它运行完美。