Заменить все смайлики из заданной строки юникода - PullRequest
0 голосов
/ 20 ноября 2018

У меня есть список символов Unicode из пакета emoji. Моя конечная цель состоит в том, чтобы создать функцию, которая принимает в качестве входных данных в кодировке Unicode строку, т.е. some??thing, а затем удаляет все эмодзи, т.е. "something". Ниже приведена демонстрация того, чего я хочу достичь:

from emoji import UNICODE_EMOJI
text = 'some??thing'
exclude_list = UNICODE_EMOJI.keys()
output = ... = 'something'

Я пытался сделать вышеупомянутое, и в этом процессе я столкнулся со странным поведением, которое я демонстрирую ниже, как вы можете видеть. Я верю, что если приведенный ниже код исправлен, я смогу достичь своей конечной цели.

import regex as re
print u'\U0001F469'                     # ?   
print u'\U0001F60C'                     # ?    
print u'\U0001F469\U0001F60C'           # ?? 

text = u'some\U0001F469\U0001F60Cthing' 
print text                              # some??thing

# Removing "??" works
print re.sub(ur'[\U0001f469\U0001F60C]+', u'', text)  # something
# Removing only "?" doesn't work 
print re.sub(ur'[\U0001f469]+', u'', text)            # some�thing

Ответы [ 3 ]

0 голосов
/ 20 ноября 2018

Старый 2.7 движок регулярных выражений запутался, потому что:

  1. В Python 2.7 используется принудительное хранение Unicode на основе слов, в котором определенные кодовые точки Unicode автоматически заменяются суррогатными парами.

  2. Прежде чем регулярное выражение "увидит" вашу строку Python, Python уже услужливо разбил ваши большие кодовые точки Unicode на два отдельных символа (каждый сам по себе является действительным, но неполным, единственным символом Unicode).

  3. Это означает, что [\U0001f469]+' заменяет что-то (класс символов из 2 символов), но один из них находится в вашей строке, а другой - нет. Это приводит к вашему плохо сформированному выводу.

Это исправляет:

print re.sub(ur'(\U0001f469|U0001F60C)+', u'', text)  # something
# Removing only "?" doesn't work 
print re.sub(ur'(\U0001f469)+', u'', text)            # some�thing
# .. and now it does:
some?thing

потому что теперь движок регулярных выражений видит ту же последовательность символов - суррогатные пары или иное - что вы ищете.

Если вы хотите удалить все эмодзи из exclude_list, вы можете явно перебрать их содержимое и заменить одно на другое:

exclude_list = UNICODE_EMOJI.keys()

for bad in exclude_list:  # or simply "for bad in UNICODE_EMOJI" if you gotta catch them all
    if bad in text:
        print 'Removing '+bad
        text = text.replace(bad, '')
Removing ?
Removing ?
something

(Это также показывает промежуточные результаты в качестве доказательства того, что это работает; вам нужна только строка replace в цикле.)

0 голосов
/ 20 ноября 2018

Чтобы удалить все смайлики из входной строки, используя текущий подход, используйте

import re
from emoji import UNICODE_EMOJI
text = u'some??thing'
exclude_list = UNICODE_EMOJI.keys()
rx = ur"(?:{})+".format("|".join(map(re.escape,exclude_list)))
print re.sub(rx, u'', text)
# => u'something'

Если вы не re.escape смайлики, вы получите ошибку nothing to repeat из-за путаницы буквальных символовдо операторов чередования внутри группы, поэтому требуется map(re.escape,exclude_list).

Протестировано в Python 2.7.12 (по умолчанию, 12 ноября 2018, 14:36:49) [GCC 5.4.0 20160609] на linux2.

0 голосов
/ 20 ноября 2018

В большинстве сборок Python 2.7 кодовые точки Unicode выше 0x10000 кодируются как суррогатная пара , что означает, что Python фактически видит их как два символа. Вы можете доказать это себе с помощью len(u'\U0001F469').

Лучший способ решить эту проблему - перейти на версию Python, которая правильно обрабатывает эти кодовые точки как единое целое, а не суррогатную пару. Вы можете скомпилировать Python 2.7 для этого, и последние версии Python 3 сделают это автоматически.

Чтобы создать регулярное выражение для replace, просто объедините все символы вместе с |. Поскольку список символов уже закодирован суррогатными парами, он создаст правильную строку.

subs = u'|'.join(exclude_list)
print re.sub(subs, u'', text)
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...