проблема с декодированием юникода - PullRequest
4 голосов
/ 26 января 2011

Это забавно ... Я пытаюсь прочитать данные географического поиска из openstreetmap.Код, выполняющий запрос, выглядит следующим образом:

params = urllib.urlencode({'q': ",".join([e for e in full_address]), 'format': "json", "addressdetails" : "1"})
query = "http://nominatim.openstreetmap.org/search?%s" % params
print query
time.sleep(5)
response = json.loads(unicode(urllib.urlopen(query).read(), "UTF-8"), encoding="UTF-8")
print response

Запрос для Цюриха правильно закодирован по URL в данных UTF-8.Здесь нет чудес.

http://nominatim.openstreetmap.org/search?q=Z%C3%BCrich%2CSWITZERLAND&addressdetails=1&format=json

Когда я распечатываю ответ, u с umlaut кодируется как latin1 (0xFC)

[{u'display_name': u'Z\xfcrich, Bezirk Z\xfcrich, Z\xfcrich, Schweiz, Europe', u'place_id': 588094, u'lon': 8.540443

, но это чепуха, потому что openstreetmap возвращает данные JSON в UTF8

Connecting to nominatim.openstreetmap.org (nominatim.openstreetmap.org)|128.40.168.106|:80... connected.
HTTP request sent, awaiting response... 
  HTTP/1.1 200 OK
  Date: Wed, 26 Jan 2011 13:48:33 GMT
  Server: Apache/2.2.14 (Ubuntu)
  Content-Location: search.php
  Vary: negotiate
  TCN: choice
  X-Powered-By: PHP/5.3.2-1ubuntu4.7
  Access-Control-Allow-Origin: *
  Content-Length: 3342
  Keep-Alive: timeout=15, max=100
  Connection: Keep-Alive
  Content-Type: application/json; charset=UTF-8
Length: 3342 (3.3K) [application/json]

, что также подтверждается содержимым файла, и затем я прямо говорю, что это UTF-8 как при чтении, так и при анализе json.

Что здесь происходит?

РЕДАКТИРОВАТЬ : очевидно, что json.loads каким-то образом облажались.

Ответы [ 2 ]

8 голосов
/ 26 января 2011

Когда я иду и распечатываю ответ, U с умлаутом кодируется латиницей 1 (0xFC)

Вы просто неверно истолковали вывод. Это строка в кодировке Unicode (вы можете сказать по префиксу u), кодировка «присоединена» отсутствует. \ XFC означает, что это кодовая точка с номером 0xFC, которая является U-Umlaut (см. http://www.fileformat.info/info/unicode/char/fc/index.htm). Причина, по которой это происходит, состоит в том, что нумерация первых 256 кодовых точек Юникода совпадает с кодировкой latin1.

Короче говоря, вы все сделали правильно - у вас есть объект Unicode с правильным контентом (который не зависит от кодировок), вы можете выбрать нужную кодировку, когда будете использовать этот контент для вывода где-то, выполнив unicodestr.encode (" utf-8 ") или с помощью кодеков, см. http://docs.python.org/howto/unicode.html#reading-and-writing-unicode-data

1 голос
/ 26 января 2011

Вывод в порядке.Всякий раз, когда вы печатаете данные на консоли, Python включает Unicode данные только при печати фактической строки.Если вы печатаете список юникодов, каждая строка юникода отображается на консоли как ее repr ():

>>> a=u'á'
>>> a
u'\xe1'
>>> print a
á
>>> [a]
[u'\xe1']
>>> print [a]
[u'\xe1']
...