Расшифровка UTF-8 URL в Python
У меня есть строка вроде "pe%20to%C5%A3i%20mai". Когда я применяю к нему urllib.parse.unquote, я получаю "pe to\u0163i mai". Если я пытаюсь записать это в файл, я получаю именно эти символы, а не ожидаемый глиф.
Как я могу преобразовать строку в utf-8, чтобы вместо этого в файле у меня был правильный глиф?
Редактировать: я использую Python 3.2
Edit2: так что я понял, что urllib.parse.unquote
работал правильно, и моя проблема на самом деле заключается в том, что я сериализовать в YAML с yaml.dump
и это, кажется, все испортило. Зачем?
4 ответа
Обновление: если выходной файл является документом yaml, вы можете игнорировать \u0163
в этом. Экранирование Unicode действительно в документах yaml.
#!/usr/bin/env python3
import json
# json produces a subset of yaml
print(json.dumps('pe toţi mai')) # -> "pe to\u0163i mai"
print(json.dumps('pe toţi mai', ensure_ascii=False)) # -> "pe toţi mai"
Примечание: нет \u
в последнем случае. Обе строки представляют одну и ту же строку Python.
yaml.dump()
имеет аналогичную опцию: allow_unicode
, Установите это True
чтобы избежать Unicode Escape.
URL правильный. Вам не нужно ничего делать с этим:
#!/usr/bin/env python3
from urllib.parse import unquote
url = "pe%20to%C5%A3i%20mai"
text = unquote(url)
with open('some_file', 'w', encoding='utf-8') as file:
def p(line):
print(line, file=file) # write line to file
p(text) # -> pe toţi mai
p(repr(text)) # -> 'pe toţi mai'
p(ascii(text)) # -> 'pe to\u0163i mai'
p("pe to\u0163i mai") # -> pe toţi mai
p(r"pe to\u0163i mai") # -> pe to\u0163i mai
#NOTE: r'' prefix
\u0163
последовательность может быть введена обработчиком ошибок кодировки символов:
with open('some_other_file', 'wb') as file: # write bytes
file.write(text.encode('ascii', 'backslashreplace')) # -> pe to\u0163i mai
Или же:
with open('another', 'w', encoding='ascii', errors='backslashreplace') as file:
file.write(text) # -> pe to\u0163i mai
Больше примеров:
# introduce some more \u escapes
b = r"pe to\u0163i mai ţţţ".encode('ascii', 'backslashreplace') # bytes
print(b.decode('ascii')) # -> pe to\u0163i mai \u0163\u0163\u0163
# remove unicode escapes
print(b.decode('unicode-escape')) # -> pe toţi mai ţţţ
Пытаться decode
с помощью unicode_escape
,
Например:
>>> print "pe to\u0163i mai".decode('unicode_escape')
pe toţi mai
Python 3
призвание urllib.parse.unquote
возвращает строку Unicode уже:
>>> urllib.parse.unquote("pe%20to%C5%A3i%20mai")
'pe toţi mai'
Если вы не получите такой результат, это должно быть ошибка в вашем коде. Пожалуйста, оставьте свой код.
Python 2
использование decode
чтобы получить строку Unicode из строки байтов:
>>> import urllib2
>>> print urllib2.unquote("pe%20to%C5%A3i%20mai").decode('utf-8')
pe toţi mai
Помните, что когда вы пишете строку Unicode в файл, вы должны снова ее кодировать. Вы можете выбрать запись в файл как UTF-8, но вы также можете выбрать другую кодировку, если хотите. Вы также должны помнить использовать ту же кодировку при чтении из файла. Вы можете найти codecs
Модуль полезен для определения кодировки при чтении и записи в файлы.
>>> import urllib2, codecs
>>> s = urllib2.unquote("pe%20to%C5%A3i%20mai").decode('utf-8')
>>> # Write the string to a file.
>>> with codecs.open('test.txt', 'w', 'utf-8') as f:
... f.write(s)
>>> # Read the string back from the file.
>>> with codecs.open('test.txt', 'r', 'utf-8') as f:
... s2 = f.read()
Одна потенциально запутанная проблема заключается в том, что в интерактивном интерпретаторе строки Unicode иногда отображаются с использованием \uxxxx
обозначение вместо реальных символов:
>>> s
u'pe to\u0163i mai'
>>> print s
pe toţi mai
Это не значит, что строка "неправильная". Просто так работает переводчик.
urllib.parse.unquote
вернул правильную строку UTF-8 и записал, что прямо в возвращенный файл дал ожидаемый результат. Проблема была с ямлом. По умолчанию это не кодирует с UTF-8.
Мое решение было сделать:
yaml.dump("pe%20to%C5%A3i%20mai",encoding="utf-8").decode("unicode-escape")
Спасибо JF Себастьяну и Марку Байерсу за то, что они задали мне правильные вопросы, которые помогли мне разобраться в проблеме!