Как удалить из текста все, кроме слов и смайликов?

В рамках проблемы классификации текста я пытаюсь очистить набор текстовых данных. До сих пор я удалял все, кроме текста. Знаки препинания, цифры, эмодзи - все убрали. Теперь я пытаюсь использовать смайлики в качестве функций, поэтому я хочу сохранить и слова, и смайлики.

Сначала я ищу эмодзи в тексте и отделяю их от других слов/эмодзи. Это связано с тем, что каждый смайлик следует рассматривать индивидуально/отдельно. Поэтому я ищу смайлик и дополняю его пробелами с обоих концов.

Но я теряюсь, пытаясь понять, как объединить известное регулярное выражение для слов и смайликов. Вот мой текущий код:

import re

def clean_text(raw_text):

    padded_emoji_text = pad_emojis(raw_text)
    print("Emoji padded text: " + padded_emoji_text)

    reg = re.compile("[^a-zA-Z]") # line a

    # old regex to remove everything except words  
    letters_only_text = reg.sub(' ', raw_text)
    print("Cleaned text: " + letters_only_text)

    # Code to remove everything except text and emojis
    # How?

def pad_emojis(raw_text):

    print("Original Text: " + raw_text)

    reg = re.compile(u'['
      u'\U0001F300-\U0001F64F'
      u'\U0001F680-\U0001F6FF'
      u'\u2600-\u26FF\u2700-\u27BF]', 
      re.UNICODE)

    #padding the emoji with space at both ends
    new_text = reg.sub(r' \g<0> ',raw_text) 

    return new_text

text = "I am very #happy man! but???????? my wife???? is not ????????. 99/33"
clean_text(text)

Текущие операции:

Original Text: I am very #happy man! but???????? my wife???? is not ????????. 99/33
Emoji padded text: I am very #happy man! but ????  ????  my wife ????  is not  ????  ???? . 99/33
Cleaned text: I am very  happy man  but   my wife  is not

Чего я пытаюсь достичь:

I am very happy man but ????  ????  my wife ????  is not  ????  ????

Вопросы:

1) Как добавить регулярное выражение emoji в компиляцию регулярного выражения вместе со словами регулярное выражение? (строка а)

2) Также могу ли я добиться того, что ищу, лучше, то есть без необходимости писать отдельную функцию только для разделения смайликов и заполнения их пробелами? Мне почему-то кажется, что этого можно избежать.


person Pale Blue Dot    schedule 21.05.2017    source источник
comment
См. эту демонстрацию Python 3 — я думаю, она показывает способ сделать это за 1 шаг. Просто не уверен, нужно ли вам сжимать пробелы или нет, ваш ожидаемый результат немного отличается от того, что я получаю.   -  person Wiktor Stribiżew    schedule 21.05.2017
comment
Эй, это здорово! Это определенно работает. Я пробовал много вариантов использования, и, похоже, все работало нормально. И да, мне нужно уменьшить пробелы, что было последним шагом очистки текста, который я не включил в вопрос. Спасибо, что позаботились об этом. А теперь не могли бы вы добавить, что это ответ? Кроме того, регулярное выражение слишком сложно для меня, чтобы понять. Будет здорово, если вы сможете в какой-то степени объяснить это в своем ответе. Большое спасибо!   -  person Pale Blue Dot    schedule 21.05.2017
comment
Хорошо, дайте мне секунду, я также добавлю здесь сокращение нескольких пробелов.   -  person Wiktor Stribiżew    schedule 21.05.2017


Ответы (1)


Вы можете объединить два шага в один, используя одно регулярное выражение и лямбда-выражение внутри re.sub следующим образом:

import re

emoji_pat = '[\U0001F300-\U0001F64F\U0001F680-\U0001F6FF\u2600-\u26FF\u2700-\u27BF]'
shrink_whitespace_reg = re.compile(r'\s{2,}')

def clean_text(raw_text):
    reg = re.compile(r'({})|[^a-zA-Z]'.format(emoji_pat)) # line a
    result = reg.sub(lambda x: ' {} '.format(x.group(1)) if x.group(1) else ' ', raw_text)
    return shrink_whitespace_reg.sub(' ', result)

text = 'I am very #happy man! but???????? my wife???? is not ????????. 99/33'
print('Cleaned text: ' + clean_text(text))
# => Cleaned text: I am very happy man but ???? ???? my wife ???? is not ???? ????

См. демонстрацию Python.

Пояснение:

  • Первое регулярное выражение будет иметь вид ([\U0001F300-\U0001F64F\U0001F680-\U0001F6FF\u2600-\u26FF\u2700-\u27BF])|[^A-Za-z] и будет соответствовать и захватывать в группу 1 эмодзи или просто соответствовать любому символу, отличному от буквы ASCII. Если смайлик был захвачен (см. if x.group(1) внутри лямбды), смайлик будет возвращен обратно, заключенный с пробелами с обеих сторон, в противном случае пробел будет использоваться для замены небуквы.
  • Шаблон \s{2,} будет соответствовать 2 или более пробелам, а shrink_whitespace_reg.sub(' ', result) заменит все эти фрагменты одним пробелом.
person Wiktor Stribiżew    schedule 21.05.2017
comment
Большое спасибо, Виктор. Вы очень помогли. - person Pale Blue Dot; 21.05.2017