如何规范化Python字符串编码

时间:2015-07-28 15:20:07

标签: python url unicode python-2.x

我有一个带字符串的文本文件。这些字符串最终表示URL路径(不是完整的URL),但已经以多种方式编码。以下是该文件的摘录:

25_%D1%80%D0%B0%D1%88%D3%99%D0%B0%D1%80%D0%B0
2_\xD1\x80\xD0\xB0\xD1\x88\xD3\x99\xD0\xB0\xD1\x80\xD0\xB0
5_%D1%80%D0%B0%D1%88%D3%99%D0%B0%D1%80%D0%B0
\xD0\x90\xD0\xBA\xD0\xB0\xD0\xB1\xD0\xB0
\xD0\x90\xD1\x88\xD3\x99\xD0\xB0\xD1\x85\xD1\x8C\xD0\xB0
function.fopen
Бразилиа
Валерии_Маиромиан
Rome,_Italy
Rome%2C_Italy

我想保证所有这些字符串的通用格式,因为加载文件后我需要进行字符串比较(例如Rome%2C_Italy应该等于Rome,_Italy)。

某些行是URL编码的,可以很容易unquoted

import urllib
with open("input.txt") as f:
    for line in f:
        str = urllib.unquote(line.rstrip())
        print str

上一代码的输出是:

25_рашәара
2_\xD1\x80\xD0\xB0\xD1\x88\xD3\x99\xD0\xB0\xD1\x80\xD0\xB0
5_рашәара
\xD0\x90\xD0\xBA\xD0\xB0\xD0\xB1\xD0\xB0
\xD0\x90\xD1\x88\xD3\x99\xD0\xB0\xD1\x85\xD1\x8C\xD0\xB0
function.fopen
Бразилиа
Валерии_Маиромиан
Rome,_Italy
Rome,_Italy

我最好的尝试是以下代码:

import urllib
with open("input.txt") as f:
    for line in f:
        str = urllib.unquote(line.rstrip()).encode("utf8")
        print str

使用以下输出:

25_рашәара
2_\xD1\x80\xD0\xB0\xD1\x88\xD3\x99\xD0\xB0\xD1\x80\xD0\xB0
5_рашәара
\xD0\x90\xD0\xBA\xD0\xB0\xD0\xB1\xD0\xB0
\xD0\x90\xD1\x88\xD3\x99\xD0\xB0\xD1\x85\xD1\x8C\xD0\xB0
function.fopen
Бразилиа
Валерии_Маиромиан
Rome,_Italy
Rome,_Italy

似乎忽略了一些行!

在任何情况下,我认为最好只对所有这些字符串进行URL编码(与行1一样),但urllib.quote()方法在已经完成的行上效果不佳URL编码(它将再次编码%!)。

感谢任何帮助以消除我的困惑!

2 个答案:

答案 0 :(得分:1)

此代码使用与Eugene Lisitsky类似的方法,除了它在Python 2上运行。可能是在Python 2中执行此操作的更简洁的方法,但它似乎可以在数据中正常工作OP。





BTW,当你提出与Unicode相关的问题时,你应该用适当的Python版本标签标记你的问题,因为Python 3中的Unicode处理与它是如何工作的(或者没有这样做:))在Python 2中。




 导入编解码器
 import urllib

 fname = 'input.txt'

 open(fname,'rb')为f:
对于f:
 line = line.strip()
 line = urllib.unquote(line)
如果r'\ x'在行中:
 line = codecs.unicode_escape_decode(line)[0]
 line = line.encode('latin1')

 line = line.decode('utf-8')
 print repr(line),line
  




output

&#xA;&#xA; < pre> u'25_ \ u0440 \ u0430 \ u0448 \ u04d9 \ u0430 \ u0440 \u0430'25_рашәара&#xA; u'2_ \ u0440 \ u0430 \ u0448 \ u04d9 \ u0430 \ u0440 \u0430'2_рашәара&#xA; u '5_ \ u0440 \ u0444 \ u0444 \ u0430 \ u0440 \u0430'5_рашәара&#xA; u'\ u0410 \ u043a \ u0430 \ u0431 \u0430'Акаба&#xA; u'\ u0410 \ u0448 \ u04d9 \ u0430 \ u0445 \ u044c \ u0430'Ашәахьа&#xA; u'function.fopen'function.fopen&#xA; u'\ u0411 \ u0440 \ u0430 \ u0437 \ u0438 \ u043b \ u0438 \u0430'Бразилиа&#xA; u'\ u0412 \ u0430 \ u043b \ u0435 \ u0440 \ u0438 \ u0438 \ u0440 \ u0438 \ u0438 \ u0440 \ u043e \ u043c \ u0438 \ u0443 \u043d'Валерии_Маиромиан&#xA; u'Rome,_Italy'Rome,_Italy&#xA; u'Rome,_Italy '罗马,_Italy&#xA; &#xA;&#xA;

如您所见,我已将所有字符串转换为Unicode对象。如果由于某种原因你想要它们作为普通的Python 2字符串,只需要消除 line = line.decode('utf-8')行。

&#xA;

答案 1 :(得分:0)

You may use codecs.unicode_escape_decode to decode backslash-escaped characters like so:

>>> import codecs
>>> s=r"\xD0\x90\xD0\xBA\xD0\xB0\xD0\xB1\xD0\xB0"
>>> print(s)
\xD0\x90\xD0\xBA\xD0\xB0\xD0\xB1\xD0\xB0
>>> s1=codecs.unicode_escape_decode(s)[0]
>>> print(s1)
Ðкаба
>>> bytes(s1,'latin1').decode('utf-8')
'Акаба'
>>>