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

时间:2017-11-21 04:33:16

标签: python utf-8 python-requests urlencode

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

当我使用requests获取JSON时,调用失败并且未找到任何结果。

使用Charles,我可以看到,在将URL粘贴到Safari并点击回车后,带有原始查询的URL(韩语单词)是URL编码的。例如,URL字符串中的소instance实例在其出路时变为%EC%86%8C%EC%8B%9D

但是,当我使用requests发出相同的请求时,该字词会被编码为%E1%84%89%E1%85%A9%E1%84%89%E1%85%B5%E1%86%A8。两种编码都可以解码回原始单词소식(使用网络应用程序确认)。前一种编码是服务器接受的,后者不是。

为什么我会从requests获得不同的编码?

修改

查询字符串以소식

的形式进入脚本

query = sys.argv[1] sys.stderr.write(query) - > 소식

将查询插入URL字符串会在打印时产生... json / word /소식....

通过查尔斯现在看起来像/json/word/%E1%84%89%E1%85%A9%E1%84%89%E1%85%B5%E1%86%A8/。一切都是默认的,没有指定的编码。

1 个答案:

答案 0 :(得分:3)

这些都是"相同"的有效网址编码。输入文字:

>>> 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
'소식'

字符串实际上并不相同,但它们在unicode中有不同的形式:

>>> 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格式。