Задать вопрос

Как получить русский текст из json на Python?

Пытаюсь распарсить json ответ на python
import requests
import json

apiUrl = "http://openapi.justin.ua/tracking/"
track = '201810165'
response = requests.get(apiUrl + track, verify=False)
obj = json.loads(response.text)
print(obj['result'][-1]['status'])

в ответе есть русские слова, но они закодированы
{"status":1,"msg":null,"result":[{"orderNumber":"201810165","orderDescription":"\u0417\u0430\u043c\u043e\u0432\u043b\u0435\u043d\u043d\u044f \u043a\u043b\u0456\u0454\u043d\u0442\u0430 201810165 \u0432\u0456\u0434 7\/25\/2018","date":"2019-02-27","time":"10:20:51","status":"\u041e\u0434\u0435\u0440\u0436\u0430\u043d\u043e","departmentNumber":"","departmentAdress":""}]}

Собственно вопрос, как из "\u041e\u0434\u0435\u0440\u0436\u0430\u043d\u043e" получить "Одержано"? Потому что даже эти символы питон не хочет выводить, выдает ошибку
UnicodeEncodeError: 'ascii' codec can't encode characters in position 0-7: ordinal not in range(128)

Пробовал декодить и энкодить по всякому, ничего не помогает((
  • Вопрос задан
  • 22638 просмотров
Подписаться 4 Простой 5 комментариев
Решения вопроса 2
@bbkmzzzz
Так проблемы с записью в файл?

json.dump(obj, fp, *, skipkeys=False, ensure_ascii=True, check_circular=True, allow_nan=True, cls=None, indent=None, separators=None, default=None, sort_keys=False, **kw)

выделенное в False, json по умолчанию юникод кодирует так. Файл должен быть открыт в utf-8
Ответ написан
trapwalker
@trapwalker Куратор тега Python
Программист, энтузиаст
Не надо там ничего энкодить и декодить.
В ответе текст в юникоде и парсится функцией `json.loads` адекватно.
Проблема скорее всего у вас из-за кодировки в консоли винды. там какая-нибудь однобайтовая кодировка вроде cp1251 или cp866.
При попытке напечатать юникод в этом терминале вы получаете ошибку из-за того, что при автоматическом преобразовании из юникода в кодировку консоли питон пытается взять кодек по умолчанию, который, конечно 'ascii'.

Винда такая винда со своим беспощадным терминалом и кодировками по умолчанию.

Но вы можете напечатать этот текст, в нём нет непечатных символов для однобайтовой кодировки. Попробуйте так:

x = obj['result'][-1]['status']
try:
    print('cp1251:', x.encode('cp1251'))
except:
    try:
        print('cp866:', x.encode('cp866'))
    except:
        print('no way')


Общие правила работы с кодировками такие:
- на входе в программу мы всё преобразовываем в юникод.
- на выходе всё кодируем в нужную кодировку.
- если выход - это печать в стандартный вывод (stdout), то ситуаций может быть 4:
1) печатаем в терминал винды и терминал у нас в кодировке 1251
2) печатаем в терминал и он у нас в 866 кодировке
3) печатаем в stdout, который перенаправлен в файл и пайп не знает в какой он кодировке, то есть кодировка не задана и мы можем заэнкодить в любую и в файл это запишется. Пользутейс utf8 - самая правильная кодировка для всего.
4) вы в линуксе и терминал у вас в кодировке по умолчанию - utf8 и всё хорошо.

В любом случае, печатая или сохраняя что-то в файл вы должны понимать, что текст нужно закодировать в кодировку. Это может произойти неявно (как в ашем случае) но при попытке закодировать в кодировку по умолчанию (ascii) не каждый символ в ней можно представить. В ASCII всего 127 символов. Получилась закономерная ошибка.

У потоков стандартного ввода/вывода есть атрибут encoding:
import sys
sys.stdout.encoding  # 'UTF-8'

В вашем случае будет либо None, если вывод перенаправлен в файл,
либо 'cp1251', либо 'cp866' ну или ещё что-нибудь эдакое.
Если не None, то в эту кодировку можно постараться заэнкодить вашу строку. По-прежнему некоторые символы могут не конвертнуться (не в вашем случае), их можно игнорировать специальным аргументом метода encode.
Ответ написан
Пригласить эксперта
Ответы на вопрос 3
@anerev
b"\u041e\u0434\u0435\u0440\u0436\u0430\u043d\u043e".decode('unicode-escape')
Ответ написан
@PaulTinnik
Возможно имеется ввиду кодировка, непосредственно при получении json от сервера.
Тогда решение такое. Проверяем текущую кодировку в библиотеке Requests.
print(responce.encoding)  # ISO-8859-1
Меняем на utf-8
<code lang="python">
responce.encoding = "utf-8"
</code>

Вместе приблизительно так: 
<code lang="python">
url = "https://your_url.me"
responce = requests.get(url=url)
responce.encoding = "utf-8" # После этой строки кириллические символы вместо экранированных
</code>
Ответ написан
Комментировать
@MAD_CHE
Проверяешь языки командой:
locale

На месте LC_CTYPE должна быть пометка UTF-8, если нет, то пишешь:
export LC_CTYPE="en_US.UTF-8"

А если не помогло, то меняй всем значениям кодировку:
export LC_ALL="en_US.UTF-8"

Я сразу прописал для всех и стал получать инфу на человеческом языке.
Ответ написан
Комментировать
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Похожие вопросы