Как можно предотвратить текст Zalgo?

Я читал о том, как работает текст Zalgo, и я хочу узнать, как программное обеспечение чата или форума может предотвратить такое раздражение? Точнее говоря, что такое полный набор символов Unicode, который должен:

а) либо быть раздетым, предполагая, что участники чата должны использовать только языки, которые не требуют комбинированных меток (то есть вы могли бы написать "жених" с комбинированной меткой, но вы были бы немного Зальго сами, если бы вы настаивали на выполнении так); или же,

б) уменьшено до максимум 8 последовательных символов ( максимум встречается в реальных языках).

РЕДАКТИРОВАТЬ: Тем временем я нашел совершенно другой вопрос (" Как защититься от... диакритики?"), Который по сути такой же, как этот. Я сделал его название более явным, чтобы другие тоже его нашли.

5 ответов

Если вы очень серьезно относитесь к этому и хотите получить техническое решение, вы можете сделать следующее:

  1. Разбить входящий текст на более мелкие единицы (слова или предложения);
  2. Визуализируйте каждую единицу на сервере с выбранным шрифтом (с огромной высотой строки и большим количеством места под базовой линией, где будет проходить "шум"Zalgo);
  3. Обучите алгоритм машинного обучения, чтобы судить, выглядит ли он слишком "темным" и "занятым";
  4. Если алгоритм имеет низкую достоверность, откладывайте на модераторов-людей.

Это может быть весело реализовать, но на практике, вероятно, лучше сразу перейти к четвертому шагу.

Редактировать: Вот более практичное, хотя и грубое, решение в Python 2.7. Символы Юникода, классифицированные как "Пометить без пробелов" и "Пометить внутри", являются основными инструментами, используемыми для создания эффекта Зальго. В отличие от приведенной выше идеи, он не будет пытаться определить "эстетику" текста, а просто удалит все такие символы. (Само собой разумеется, это будет мусор текста на многих языках. Читайте дальше для лучшего решения.) Чтобы отфильтровать больше категорий символов, добавьте их в ZALGO_CHAR_CATEGORIES,

#!/usr/bin/env python
import unicodedata
import codecs

ZALGO_CHAR_CATEGORIES = ['Mn', 'Me']

with codecs.open("zalgo", 'r', 'utf-8') as infile:
    for line in infile:
        print ''.join([c for c in unicodedata.normalize('NFD', line) if unicodedata.category(c) not in ZALGO_CHAR_CATEGORIES]),

Пример ввода:

1
H̡̫̤ͭ̓̓̇͗̎̀ơ̯̗͒̄̀̈ͤ̀͡w͓̲͙͋ͬ̊ͦ̂̀̚ ͎͉͖̌ͯͅͅd̳̘̿̃̔̏ͣ͂̉̕ŏ̖̙͋ͤ̊͗̓͟͜e͈͕̯̮͌ͭ̍̐̃͒s͙͔̺͇̗̱̿̊̇͞ ̸ͩͩ͑̋̀ͮͥͦ̊Z̆̊͊҉҉̠̱̦̩͕ą̟̹͈̺̹̋̅ͯĺ̡̘̹̻̩̩͋͘g̪͚͗ͬ͒o̢̖͇̬͍͇̔͋͊̓ ̢͈͂ͣ̏̿͐͂ͯ͠t̛͓̖̻̲ͤ̈ͣ͝e͋̄ͬ̽͜҉͚̭͇ͅx̌ͤ̓̂̓͐͐́͋͡ț̗̹̄̌̀ͧͩ̕͢ ̮̗̩̳̱̾w͎̭̤̄͗ͭ̃͗ͮ̐o̢̯̻̾ͣͬ̽̔̍͟r̢̪͙͍̠̀ͅǩ̵̶̗̮̮ͪ́?̙͉̥̬ͤ̌͗ͩ̕͡
2
H̡̫̤ͭ̓̓̇͗̎̀ơ̯̗͒̄̀̈ͤ̀͡w͓̲͙͋ͬ̊ͦ̂̀̚ ͎͉͖̌ͯͅͅd̳̘̿̃̔̏ͣ͂̉̕ŏ̖̙͋ͤ̊͗̓͟͜e͈͕̯̮͌ͭ̍̐̃͒s͙͔̺͇̗̱̿̊̇͞ ̸ͩͩ͑̋̀ͮͥͦ̊Z̆̊͊҉҉̠̱̦̩͕ą̟̹͈̺̹̋̅ͯĺ̡̘̹̻̩̩͋͘g̪͚͗ͬ͒o̢̖͇̬͍͇̔͋͊̓ ̢͈͂ͣ̏̿͐͂ͯ͠t̛͓̖̻̲ͤ̈ͣ͝e͋̄ͬ̽͜҉͚̭͇ͅx̌ͤ̓̂̓͐͐́͋͡ț̗̹̄̌̀ͧͩ̕͢ ̮̗̩̳̱̾w͎̭̤̄͗ͭ̃͗ͮ̐o̢̯̻̾ͣͬ̽̔̍͟r̢̪͙͍̠̀ͅǩ̵̶̗̮̮ͪ́?̙͉̥̬ͤ̌͗ͩ̕͡
3

Выход:

1
How does Zalgo text work?
2
How does Zalgo text work?
3

Наконец, если вы хотите обнаружить, а не безоговорочно удалить текст Zalgo, вы можете выполнить анализ частоты символов. Программа ниже делает это для каждой строки входного файла. Функция is_zalgo вычисляет "счет Zalgo" для каждого слова заданной строки (оценка - это число потенциальных символов Zalgo, деленное на общее количество символов). Затем он выглядит, если третий квартиль оценки слов больше, чем THRESHOLD, Если THRESHOLD равняется 0.5 это означает, что мы пытаемся определить, содержит ли каждое из четырех слов более 50% символов Zalgo. (The THRESHOLD 0,5 было угадано и может потребовать корректировки для реального использования.) Этот тип алгоритма, вероятно, является лучшим с точки зрения отдачи / усилий по кодированию.

#!/usr/bin/env python
from __future__ import division
import unicodedata
import codecs
import numpy

ZALGO_CHAR_CATEGORIES = ['Mn', 'Me']
THRESHOLD = 0.5
DEBUG = True

def is_zalgo(s):
    if len(s) == 0:
        return False
    word_scores = []
    for word in s.split():
        cats = [unicodedata.category(c) for c in word]
        score = sum([cats.count(banned) for banned in ZALGO_CHAR_CATEGORIES]) / len(word)
        word_scores.append(score)
    total_score = numpy.percentile(word_scores, 75)
    if DEBUG:
        print total_score
    return total_score > THRESHOLD

with codecs.open("zalgo", 'r', 'utf-8') as infile:
    for line in infile:
        print is_zalgo(unicodedata.normalize('NFD', line)), "\t", line

Образец вывода:

0.911483990148
True    Señor, could you or your fiancé explain, H̡̫̤ͭ̓̓̇͗̎̀ơ̯̗͒̄̀̈ͤ̀͡w͓̲͙͋ͬ̊ͦ̂̀̚ ͎͉͖̌ͯͅͅd̳̘̿̃̔̏ͣ͂̉̕ŏ̖̙͋ͤ̊͗̓͟͜e͈͕̯̮͌ͭ̍̐̃͒s͙͔̺͇̗̱̿̊̇͞ ̸ͩͩ͑̋̀ͮͥͦ̊Z̆̊͊҉҉̠̱̦̩͕ą̟̹͈̺̹̋̅ͯĺ̡̘̹̻̩̩͋͘g̪͚͗ͬ͒o̢̖͇̬͍͇̔͋͊̓ ̢͈͂ͣ̏̿͐͂ͯ͠t̛͓̖̻̲ͤ̈ͣ͝e͋̄ͬ̽͜҉͚̭͇ͅx̌ͤ̓̂̓͐͐́͋͡ț̗̹̄̌̀ͧͩ̕͢ ̮̗̩̳̱̾w͎̭̤̄͗ͭ̃͗ͮ̐o̢̯̻̾ͣͬ̽̔̍͟r̢̪͙͍̠̀ͅǩ̵̶̗̮̮ͪ́?̙͉̥̬ͤ̌͗ͩ̕͡

0.333333333333
False   Příliš žluťoučký kůň úpěl ďábelské ódy.  

Сделать коробку overflow:hidden, На самом деле он не отключает текст Zalgo, но предотвращает повреждение других комментариев.

<style>
.comment {
  /* the overflow: hidden is what prevents one comment's combining marks from affecting its siblings */
  overflow: hidden;
  /* the padding gives space for any legitimate combining marks */
  padding: 0.5em;
  /* the rest are just to visually divide the three comments */
  border: solid 1px #ccc;
  margin-top: -1px;
  margin-bottom: -1px;
}
</style>
<div class=comment>The below comment looks aweful.</div>
<div class=comment>H̡̫̤ͭ̓̓̇͗̎̀ơ̯̗͒̄̀̈ͤ̀͡w͓̲͙͋ͬ̊ͦ̂̀̚ ͎͉͖̌ͯͅͅd̳̘̿̃̔̏ͣ͂̉̕ŏ̖̙͋ͤ̊͗̓͟͜e͈͕̯̮͌ͭ̍̐̃͒s͙͔̺͇̗̱̿̊̇͞ ̸ͩͩ͑̋̀ͮͥͦ̊Z̆̊͊҉҉̠̱̦̩͕ą̟̹͈̺̹̋̅ͯĺ̡̘̹̻̩̩͋͘g̪͚͗ͬ͒o̢̖͇̬͍͇̔͋͊̓ ̢͈͂ͣ̏̿͐͂ͯ͠t̛͓̖̻̲ͤ̈ͣ͝e͋̄ͬ̽͜҉͚̭͇ͅx̌ͤ̓̂̓͐͐́͋͡ț̗̹̄̌̀ͧͩ̕͢ ̮̗̩̳̱̾w͎̭̤̄͗ͭ̃͗ͮ̐o̢̯̻̾ͣͬ̽̔̍͟r̢̪͙͍̠̀ͅǩ̵̶̗̮̮ͪ́?̙͉̥̬ͤ̌͗ͩ̕͡</div>
<div class=comment>The above comment looks aweful.</div>

Предварительный просмотр на JSFiddle

Соответствующий вопрос задавался ранее: https://stackru.com/questions/5073191/how-is-zalgo-text-implemented но здесь интересно заняться профилактикой.

С точки зрения предотвращения этого вы можете выбрать несколько стратегий:

  1. предотвратить полное объединение диакритических знаков (и разозлить многих международных пользователей),
  2. отфильтровывать комбинированные символы, используя белый или черный список (и разозлить меньший процент международных пользователей)
  3. предотвратить определенное количество комбинируемых символов (и разозлить еще меньший процент пользователей)
  4. иметь здоровое модераторское сообщество (со всеми недостатками, которые есть, смотрите ваш вопрос в качестве примера здесь)

Вы можете избавиться от текста Zalgo в своем приложении, используя метки комбинирования полос Матиаса Биненса.

Маркировка совмещения модулей доступна для браузеров (через Bower) и приложений Node.js (через npm).

Вот пример того, как использовать его с npm:

var stripCombiningMarks = require("strip-combining-marks");
var zalgoText = 'U̼̥̻̮͍͖n͠i͏c̯̮o̬̝̠͉̤d͖͟e̫̟̗͟ͅ';
var stripptedText = stripCombiningMarks(zalgoText); // "Unicode"

Используя PHP и образ мышления работника по сносу, вы можете избавиться от Zalgo с помощью функции iconv. Конечно, это убьет и любые другие символы UTF-8.

$unZalgoText = iconv("UTF-8", "ISO-8859-1//IGNORE", $zalgoText);
Другие вопросы по тегам