Предупреждение возникает при вставке 4-байтового Unicode в MySQL

Посмотрите на следующее:

/home/kinka/workspace/py/tutorial/tutorial/pipelines.py:33: Warning: Incorrect string 
value: '\xF0\x9F\x91\x8A\xF0\x9F...' for column 't_content' at row 1
n = self.cursor.execute(self.sql, (item['topic'], item['url'], item['content']))

Строка'\xF0\x9F\x91\x8AНа самом деле это 4-байтовый юникод:u'\U0001f62a', Набор символов mysql - это utf-8, но при вставке 4-байтового Unicode он усекает вставленную строку. Я гуглил такую проблему и обнаружил, что mysql под 5.5.3 не поддерживает 4-байтовый юникод, и, к сожалению, мой - 5.5.224. Я не хочу обновлять сервер MySQL, поэтому я просто хочу отфильтровать 4-байтовый Unicode в Python, я попытался использовать регулярное выражение, но не получилось. Итак, любая помощь?

 Martijn Pieters♦29 мая 2012 г., 14:54
Да, и'\xF0\x9F\x91\x8A'.decode('utf8') являетсяu'\U0001f44a', который'FISTED HAND SIGN' :-)
 Martijn Pieters♦29 мая 2012 г., 13:59
Это цвет смайликов кулак руки:...
 mata29 мая 2012 г., 14:01
@MartijnPieters -unicodedata.name("\U0001f62a") говорит'SLEEPY FACE' (что было быb'\xf0\x9f\x98\xaa' в utf-8), поэтому что-то здесь не так ...
 Kinka29 мая 2012 г., 14:08
На самом деле, это сонное лицо. Я очищаю страницы отsina weibo(твиттер в китае) а я такую соскобилSLEEP FACE.

Ответы на вопрос(3)

тебе следует использовать сортировку utf8mb4 вместо utf8 и запустить

SET NAMES UTF8MB4

после соединения с БД ссылк, ссылк, ссылк)

 bobince23 июл. 2015 г., 13:38
Установка соединения для использованияutf8mb4 - лучший подход, но вы не должны делать это сSET NAMES. Эта команда изменяет настройку соединения на стороне сервера, не сообщая клиентской библиотеке об изменении, что означает, что все в клиентской библиотеке использует Cmysql_real_escape_string API может привести к плохим результатам. Это может привести к дырам в безопасности SQL-инъекций, если для многобайтовой кодировки Восточной Азии используется одна или обе кодировки. Наборы символов должны быть установлены во время подключения; в Python-MySQL это будет сделано с помощьюcharset аргументconnect().

def normalize_unicode(s):
    return ''.join([ unichr(k) if k < 0x10000 else 0xfffd for k in [ord(c) for c in s]])
Решение Вопроса

тогда вам придется отфильтровать все символы Юникода по кодовой точке\U00010000; UTF-8 кодирует кодовые точки ниже этого порога в 3 байта или меньше.

Для этого можно использовать регулярное выражение:

>>> import re
>>> highpoints = re.compile(u'[\U00010000-\U0010ffff]')
>>> example = u'Some example text with a sleepy face: \U0001f62a'
>>> highpoints.sub(u'', example)
u'Some example text with a sleepy face: '

Кроме того, вы можете использовать.translate() функция с таблицей сопоставления, которая содержит толькоNone значения

>>> nohigh = { i: None for i in xrange(0x10000, 0x110000) }
>>> example.translate(nohigh)
u'Some example text with a sleepy face: '

Однако создание таблицы перевода потребует много памяти и займет некоторое время; это, вероятно, не стоит ваших усилий, поскольку подход с регулярными выражениями более эффективен.

Это предполагает, что вы используете скомпилированный питон UCS-4. Если ваш питон был скомпилирован с поддержкой UCS-2, то вы можете использовать только кодовые точки до'\U0000ffff' в регулярных выражениях, и вы никогда не столкнетесь с этой проблемой в первую очередь.

Замечу, что с MySQL 5.5.3 недавно добавленныйutf8mb4 кодек действительно поддерживает полный диапазон Unicode.

 Michael Waterfall05 сент. 2012 г., 20:33
Любая идея, почему я получаю сообщение об ошибке:re.compile(u'[\U00010000-\U0010ffff]') "/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/re.py", line 244, in _compile raise error, v # invalid expression sre_constants.error: bad character range
 Martijn Pieters♦29 мая 2012 г., 15:10
Ты совершенно прав; исправлено использование правильных 8-байтовых escape-последовательностей. Сначала у меня возникли некоторые проблемы из-за использования скомпилированного Python UCS2: -P
 Kinka29 мая 2012 г., 15:12
Но в моем случае это действительно важно, строчные или нет. Я используюhighpoints = re.compile(u'[\U00010000-\U0001ffff]') и это работает. Кажется, что в моем компьютере (это проблема версии Python? У меня это Python 2.7). С прописными буквами\U, Unicode поддерживает гораздо больший диапазон.
 Martijn Pieters♦29 мая 2012 г., 15:12
Нет, ты совершенно прав. Я также опустил нижнюю границу, понимая, что неправильно прочитал таблицу UTF-8.
 Kinka29 мая 2012 г., 14:59
Я попробовал твой код, но он не работает. Это\U(верхний регистрu). Тем не менее, ваша мысль действительно поучительна, спасибо!

Ваш ответ на вопрос