Разбор строки не в Юникоде с Flask -RESTful - PullRequest
0 голосов
/ 15 февраля 2020

У меня есть webhook, разработанный с Flask -RESTful, который получает несколько параметров с помощью POST. Одним из параметров является не-Unicode строка, закодированная в cp1251 .

Не могу найти способ правильно проанализировать этот аргумент, используя reqparse.

Вот фрагмент моего кода:

parser = reqparse.RequestParser()
parser.add_argument('text')
msg = parser.parse_args()

Затем я пишу msg в текстовый файл, и он выглядит так:

{"text": "\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd !\n\n\ufffd\ufffd\ufffd\ufffd\ufffd\n\n-- \n\ufffd \ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd."}

Как видите, Flask каким-то образом заменяет все символы кириллицы c на \ufffd. В то же время не-кириллические c символы, такие как ! или \n, обрабатываются правильно.

Что я могу сделать, чтобы посоветовать RequestParser с кодировкой строки?

Здесь мой код для записи текста на диск:

 f = open('log_msg.txt', 'w+')
 f.write(json.dumps(msg))
 f.close()

Я попытался f = open('log_msg.txt', 'w+', encoding='cp1251') с тем же результатом.

Затем я попытался

 f = open('log_msg_ascii.txt', 'w+')
 f.write(ascii(json.dumps(msg)))

Также, без разницы.

Итак, я почти уверен, что RequestParser() пытается быть слишком умным и не может понять ввод не-Unicode.

Спасибо!

1 Ответ

1 голос
/ 19 февраля 2020

Хорошо, я наконец нашел обходной путь. Спасибо @lenz за помощь в решении этой проблемы. Кажется, что reqparse ошибочно предполагает, что каждый строковый параметр имеет вид UTF-8. Поэтому, когда он видит поле ввода, отличное от Unicode (среди других полей Unicode!), Он пытается загрузить его как Unicode и завершается неудачей. В результате все символы U+FFFD (символ замены).

Итак, чтобы получить доступ к полю, отличному от Unicode, я проделал следующий трюк.

Сначала я загружаю необработанные данные, используя get_data(), расшифруйте его с помощью cp1251 и проанализируйте с помощью простого регулярного выражения.

 raw_data = request.get_data()
 contents = raw_data.decode('windows-1251')
 match = re.search(r'(?P<delim>--\w+\r?\n)Content-Disposition: form-data; name=\"text\"\r?\n(.*?)(?P=delim)', contents, re.MULTILINE | re.DOTALL)
 text = match.group(2)

Не самое красивое решение, но оно работает.

...