如何标准化 Python 字符串编码
How to normalize Python string encodings
我有一个包含字符串的文本文件。这些字符串最终表示 URL 路径(不是完整的 URLs),但已经以多种方式编码。这是文件的摘录:
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 编码的行上(它将再次编码 %
!)。
感谢任何帮助我解决困惑的人!
您可以使用 codecs.unicode_escape_decode 解码反斜杠转义字符,如下所示:
>>> 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')
'Акаба'
>>>
此代码使用与 Eugene Lisitsky 类似的方法,不同之处在于它在 Python 2 上运行。可能 是在 [=25= 中执行此操作的更简洁方法] 2,但它似乎可以在 OP 中的数据上正常工作。
顺便说一句,当您提出与 Unicode 相关的问题时,您应该使用适当的 Python 版本标记来标记您的问题,因为 Python 3 中的 Unicode 处理与其工作方式(或未能这样做 :) ) 在 Python 2.
import codecs
import urllib
fname = 'input.txt'
with open(fname, 'rb') as f:
for line in f:
line = line.strip()
line = urllib.unquote(line)
if r'\x' in line:
line = codecs.unicode_escape_decode(line)[0]
line = line.encode('latin1')
line = line.decode('utf-8')
print repr(line), line
输出
u'25_\u0440\u0430\u0448\u04d9\u0430\u0440\u0430' 25_рашәара
u'2_\u0440\u0430\u0448\u04d9\u0430\u0440\u0430' 2_рашәара
u'5_\u0440\u0430\u0448\u04d9\u0430\u0440\u0430' 5_рашәара
u'\u0410\u043a\u0430\u0431\u0430' Акаба
u'\u0410\u0448\u04d9\u0430\u0445\u044c\u0430' Ашәахьа
u'function.fopen' function.fopen
u'\u0411\u0440\u0430\u0437\u0438\u043b\u0438\u0430' Бразилиа
u'\u0412\u0430\u043b\u0435\u0440\u0438\u0438_\u041c\u0430\u0438\u0440\u043e\u043c\u0438\u0430\u043d' Валерии_Маиромиан
u'Rome,_Italy' Rome,_Italy
u'Rome,_Italy' Rome,_Italy
如您所见,我已将所有字符串转换为 Unicode 对象。如果出于某种原因你希望它们是普通的 Python 2 字符串,只需删除 line = line.decode('utf-8')
行。
我有一个包含字符串的文本文件。这些字符串最终表示 URL 路径(不是完整的 URLs),但已经以多种方式编码。这是文件的摘录:
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 编码的行上(它将再次编码 %
!)。
感谢任何帮助我解决困惑的人!
您可以使用 codecs.unicode_escape_decode 解码反斜杠转义字符,如下所示:
>>> 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')
'Акаба'
>>>
此代码使用与 Eugene Lisitsky 类似的方法,不同之处在于它在 Python 2 上运行。可能 是在 [=25= 中执行此操作的更简洁方法] 2,但它似乎可以在 OP 中的数据上正常工作。
顺便说一句,当您提出与 Unicode 相关的问题时,您应该使用适当的 Python 版本标记来标记您的问题,因为 Python 3 中的 Unicode 处理与其工作方式(或未能这样做 :) ) 在 Python 2.
import codecs
import urllib
fname = 'input.txt'
with open(fname, 'rb') as f:
for line in f:
line = line.strip()
line = urllib.unquote(line)
if r'\x' in line:
line = codecs.unicode_escape_decode(line)[0]
line = line.encode('latin1')
line = line.decode('utf-8')
print repr(line), line
输出
u'25_\u0440\u0430\u0448\u04d9\u0430\u0440\u0430' 25_рашәара
u'2_\u0440\u0430\u0448\u04d9\u0430\u0440\u0430' 2_рашәара
u'5_\u0440\u0430\u0448\u04d9\u0430\u0440\u0430' 5_рашәара
u'\u0410\u043a\u0430\u0431\u0430' Акаба
u'\u0410\u0448\u04d9\u0430\u0445\u044c\u0430' Ашәахьа
u'function.fopen' function.fopen
u'\u0411\u0440\u0430\u0437\u0438\u043b\u0438\u0430' Бразилиа
u'\u0412\u0430\u043b\u0435\u0440\u0438\u0438_\u041c\u0430\u0438\u0440\u043e\u043c\u0438\u0430\u043d' Валерии_Маиромиан
u'Rome,_Italy' Rome,_Italy
u'Rome,_Italy' Rome,_Italy
如您所见,我已将所有字符串转换为 Unicode 对象。如果出于某种原因你希望它们是普通的 Python 2 字符串,只需删除 line = line.decode('utf-8')
行。