代码之家  ›  专栏  ›  技术社区  ›  Canucklesandwich

URL编码会产生两种不同的结果?只有一个可行

  •  0
  • Canucklesandwich  · 技术社区  · 8 年前

    我正在写一个Python脚本来获取韩语词汇发音。我已经准备好了一个URL,当我在Safari中打开该URL时,它会从服务器检索预期的JSON。

    当我使用 requests 为了获取JSON,调用失败,没有找到任何结果。

    使用Charles,我可以看到,在我将URL粘贴到Safari并按enter键后,带有原始查询的URL(一个朝鲜文单词)是URL编码的。例如,URL字符串中的ìì的实例变为 %EC%86%8C%EC%8B%9D 在离开的路上。

    然而,当我向 请求 ,单词编码为 %E1%84%89%E1%85%A9%E1%84%89%E1%85%B5%E1%86%A8 . 这两种编码都可以解码回原始单词ìì(使用web应用程序进行确认)。服务器接受前一种编码,但不接受后一种编码。

    为什么我会从 请求 ?

    编辑

    查询字符串以소식的形式进入脚本

    query = sys.argv[1] sys.stderr.write(query) -&燃气轮机;ìì

    将查询插入URL字符串会产生。。。json/word/ìì。。。打印时。

    经过Charles现在看起来是这样的 /json/word/%E1%84%89%E1%85%A9%E1%84%89%E1%85%B5%E1%86%A8/ . 一切都是默认的,没有指定的编码。

    1 回复  |  直到 8 年前
        1
  •  3
  •   wim    8 年前

    这两种都是“相同”输入文本的有效url编码:

    >>> from urllib.parse import unquote
    >>> ulong = unquote('%E1%84%89%E1%85%A9%E1%84%89%E1%85%B5%E1%86%A8')
    >>> ushort = unquote('%EC%86%8C%EC%8B%9D')
    >>> ulong
    '소식'
    >>> ushort
    '소식'
    

    >>> from unicodedata import name
    >>> [name(x) for x in ulong]
    ['HANGUL CHOSEONG SIOS',
     'HANGUL JUNGSEONG O',
     'HANGUL CHOSEONG SIOS',
     'HANGUL JUNGSEONG I',
     'HANGUL JONGSEONG KIYEOK']
    >>> [name(x) for x in ushort]
    ['HANGUL SYLLABLE SO', 'HANGUL SYLLABLE SIG']
    

    我不知道任何韩语,但它看起来像是由组合字符组成的长字符串(你也可以看到类似的事情与拉丁字符和重音)。如果我对形式进行规范分解和组合,我得到等式:

    >>> from unicodedata import normalize
    >>> normalize('NFC', ulong) == ushort
    True
    

    所以,要么你使用的是不同的输入文本,要么看起来是一样的(甚至 repr 还不足以看到差异,您必须检查代码点)或您正在使用的方法之一(可能是浏览器)正在执行规范化/转换。

    由于文本的简短形式是服务器的工作方式,我建议您将脚本的输入规范化为NFC形式。