在 Python 2.7 中,给定一个像 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
这样的 URL,我怎样才能将它解码为预期的结果,example.com?title==правовая+защита
?
我试了url=urllib.unquote(url.encode("utf8"))
,但似乎给出了错误的结果。
数据是使用 URL 引号转义的 UTF-8 编码字节,因此您需要使用 urllib.parse.unquote()
进行 decode,它透明地处理从百分比编码数据到 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')
如果你使用的是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=правовая+защита'
您也可以使用 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
,可能会很方便,而无需为此工作使用其他库。
在 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'))
我知道这是一个老问题,但我通过谷歌搜索偶然发现了这个问题,发现没有人提出只有内置功能的解决方案。
所以我很快写了自己的。
基本上一个url字符串只能包含这些字符:A-Z, a-z, 0-9, -, ., _, ~, :, /, ?, #, [, ], @, !, $, &, ', ( , ), *, +, ,, ;, %, 和 =,其他所有内容都是 url 编码的。
URL 编码非常简单,只是一个百分号后跟对应于非法字符代码点的字节值的十六进制数字。
所以基本上使用一个简单的 while 循环来迭代字符,如果它不是百分号,则按原样添加任何字符的字节,将索引递增 1,否则添加百分号后面的字节并将索引递增 3,累积字节和解码它们应该可以完美地工作。
代码如下:
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')
我已经测试过了,效果很好。