Предупреждение возникает при вставке 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-байтовый Unicode: u'\U0001f62a'
, Набор символов mysql - utf-8, но при вставке 4-байтового Unicode он усекает вставленную строку. Я гуглил такую проблему и обнаружил, что mysql под 5.5.3 не поддерживает 4-байтовый юникод, и, к сожалению, мой - 5.5.224. Я не хочу обновлять сервер MySQL, поэтому я просто хочу отфильтровать 4-байтовый Unicode в Python, я пытался использовать регулярное выражение, но не получилось. Итак, любая помощь?
3 ответа
Если MySQL не может обрабатывать коды UTF-8 длиной 4 байта или более, вам придется отфильтровать все символы Юникода по кодам \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.
Простая нормализация для строки без регулярных выражений и перевода:
def normalize_unicode(s):
return ''.join([ unichr(k) if k < 0x10000 else 0xfffd for k in [ord(c) for c in s]])