如何正确取消引用应该包含日文符号的 url

How to correctly unquote url which is supposed to contain Japanese symbols

例如,我有以下字符串(这是我根据错误编码的字符串构建的)

https://ja-jp.facebook.com/%C3%A5%C2%90%C2%8D%C3%A5%C2%8F%C2%A4%C3%A5%C2%B1%E2%80%B9%C3%AF%C2%BD%C5%A0%C3%AF%C2%BD%E2%80%99%C3%A3%E2%80%9A%C2%B2%C3%A3%C6%92%C2%BC%C3%A3%C6%92%CB%86%C3%A3%E2%80%9A%C2%BF%C3%A3%C6%92%C2%AF%C3%A3%C6%92%C2%BC%C3%A3%C6%92%E2%80%BA%C3%A3%C6%92%E2%80%A0%C3%A3%C6%92%C2%AB-219123305237478

这个 url 可以被浏览器正确解码,显示如下:

https://ja-jp.facebook.com/名古屋jrゲートタワーホテル-219123305237478/

有没有办法 unquote/decode 字符串,所以它不是这样显示的:

https://ja-jp.facebook.com/åå¤å±‹ï½Šï½’ゲートタワーホテル-219123305237478

浏览器最初在短时间内显示 url 相同的垃圾,但随后在没有重定向的情况下调整了字符串,使其看起来正常。

我正在尝试使用这个简单的代码修复编码:

def fix_encoding(s):
    for a in aliases:
        for b in aliases:
            try:
                fixed = s.encode(a).decode(b)
            except:
                pass
            else:
                print (a, b)
                print(fixed)

fix_encoding(u'åå¤å±‹ï½Šï½’ゲートタワーホテル-219123305237478')

我得到的最佳结果非常接近它应该看起来的样子,但是对于所有相同的结果,前 2 个符号都是错误的。例如:

��屋jrゲートタワーホテル-219123305237478
('1252', 'l8')

本来想删掉这个问题的,因为好像没什么意义,不过既然已经得到了一些分数,我就此分享一些想法。

url 很可能是在 Facebook 上以这种方式创建的,因为非 utf-8 编码的文本是从某处复制的(或者甚至是过去 facebook 上的一些错误)。某些页面在 updateURI 属性 附近的脚本中包含正确编码的 uri,这似乎被 js 用于更新浏览器地址字符串中的 url。

这个 url 可能是在可能的情况下自动创建的,或者可能是手动添加的,所以搜索引擎中的旧 url 仍然受到尊重。因此,找到一种修复此类错误的通用方法很可能毫无意义。

第一个URL坏了。发生的事情是,一些软件认为正确的 UTF-8 URL 是 CP1252,即使 CP1252 中有一些字节无效。因此它将正确 URL 的字节从假定的 CP1252 转换为 UTF8,但当且仅当字节在 CP1252 中有效时。无效字节保持原样。这就是为什么所有 URL 不能通过一种编码-解码组合恢复的原因。

要反转所描述的过程,我们需要例如以下代码(在 Python 2 中):

#-*-coding:utf8-*-
from six.moves.urllib import parse

correct = 'https://ja-jp.facebook.com/名古屋jrゲートタワーホテル-219123305237478'
url = 'https://ja-jp.facebook.com/%C3%A5%C2%90%C2%8D%C3%A5%C2%8F%C2%A4%C3%A5%C2%B1%E2%80%B9%C3%AF%C2%BD%C5%A0%C3%AF%C2%BD%E2%80%99%C3%A3%E2%80%9A%C2%B2%C3%A3%C6%92%C2%BC%C3%A3%C6%92%CB%86%C3%A3%E2%80%9A%C2%BF%C3%A3%C6%92%C2%AF%C3%A3%C6%92%C2%BC%C3%A3%C6%92%E2%80%BA%C3%A3%C6%92%E2%80%A0%C3%A3%C6%92%C2%AB-219123305237478'
unq_url = parse.unquote(url.encode('ascii'))

res = ''
for c in unq_url.decode('utf8'):
    try:
        res += c.encode('cp1252')
    except:
        res += chr(ord(c))

print res == correct