Как реализовать хороший фильтр ненормативной лексики?

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

Где можно найти хороший список нецензурных слов на разных языках и диалектах?

Доступны ли API для источников, которые содержат хорошие списки? Или, может быть, API, который просто говорит "да, это чисто" или "нет, это грязно" с некоторыми параметрами?

Какие есть хорошие методы для ловли людей, пытающихся обмануть систему, например, $$, azz или a55?

Бонусные баллы, если вы предлагаете решения для PHP.:)

Изменить: Ответ на ответы, которые говорят, просто избежать программной проблемы:

Я думаю, что есть место для такого рода фильтров, когда, например, пользователь может использовать общедоступный поиск изображений, чтобы найти изображения, которые будут добавлены в пул конфиденциальных сообществ. Если они могут искать "пенис", то они, скорее всего, получат много фотографий, да. Если нам не нужны картинки этого, то предотвращение слова в качестве поискового запроса - это хороший привратник, хотя и не надежный метод. Получение списка слов в первую очередь является реальным вопросом.

Так что я действительно имею в виду способ выяснить, является ли грязный токен грязным или нет, а затем просто запретить его. Я бы не стал предотвращать такое чувство, как совершенно смешное упоминание о "длинношерстном жирафе". Вы ничего не можете сделать там.:)

20 ответов

Решение

Фильтры непристойности: плохая идея или невероятно слаженная плохая идея?

Кроме того, нельзя не вспомнить "Неописанную историю" SpeedChat в Тоунтауне, где даже использование "белого списка безопасных слов" привело к тому, что 14-летний парень быстро обошел его: "Я хочу засунуть своего жирафа с длинной шеей в ваш пушистый белый кролик".".

Итог: в конечном счете, для любой системы, которую вы внедряете, абсолютно ничто не заменит человеческого обзора (независимо от того, является ли он аналогичным или нет). Не стесняйтесь реализовывать элементарный инструмент, чтобы избавиться от попутчиков, но для решительного тролля вам абсолютно необходим подход, не основанный на алгоритме.

Также полезна система, которая устраняет анонимность и вводит подотчетность (что хорошо справляется с переполнением стека), особенно для борьбы с ПОДАРОКОМ Джона Габриэля

Вы также спросили, где вы можете получить списки ненормативной лексики, чтобы начать - один проект с открытым исходным кодом, который нужно проверить, это http://dansguardian.org/ - проверьте исходный код для списков ненормативной лексики по умолчанию. Существует также дополнительный список фраз сторонних производителей, который вы можете загрузить для прокси-сервера, который может быть полезным для вас.

Отредактируйте в ответ на вопрос edit: Спасибо за разъяснение того, что вы пытаетесь сделать. В этом случае, если вы просто пытаетесь сделать простой фильтр слов, есть два способа сделать это. Один из них - создать одно длинное регулярное выражение со всеми запрещенными фразами, которые вы хотите подвергнуть цензуре, и просто выполнить поиск / замену регулярного выражения. Регулярное выражение, подобное:

$filterRegex = "(boogers|snot|poop|shucks|argh)"

и запустите его на входной строке, используя preg_match(), чтобы протестировать результат на хит,

или preg_replace() чтобы убрать их.

Вы также можете загружать эти функции с массивами, а не с одним длинным регулярным выражением, и для длинных списков слов это может быть более управляемым. Смотрите preg_replace() для некоторых хороших примеров того, как можно гибко использовать массивы.

Дополнительные примеры программирования на PHP см. На этой странице с несколько более сложным универсальным классом для фильтрации слов, который * выделяет центральные буквы из цензурированных слов, и этот предыдущий вопрос о переполнении стека, в котором также есть пример PHP (основная ценная часть которого есть основанный на SQL подход фильтрованного слова - можно обойтись без компенсатора речи, если вы сочтете это ненужным).

Вы также добавили: " Получение списка слов в первую очередь является реальным вопросом". В дополнение к некоторым предыдущим ссылкам Дансгаурда, вам может пригодиться этот полезный ZIP- файл из 458 слов.

Хотя я знаю, что этот вопрос довольно старый, но это часто встречающийся вопрос...

Существует как причина, так и явная потребность в фильтрах ненормативной лексики (см. Статью в Википедии здесь), но они часто не достигают 100% точности по совершенно разным причинам; Контекст и точность.

Это зависит (целиком) от того, чего вы пытаетесь достичь - в самом основном, вы, вероятно, пытаетесь охватить " семь грязных слов ", а затем и некоторые... Некоторым предприятиям необходимо отфильтровать самое основное из ненормативной лексики: основной ругайтесь словами, URL-адресами или даже личной информацией и т. д., но другие должны предотвращать незаконное присвоение имен учетным записям (например, Xbox live) или многое другое...

Пользовательский контент не только содержит потенциальные нецензурные слова, он также может содержать оскорбительные ссылки на:

  • Половые акты
  • Сексуальная ориентация
  • религия
  • Этнос
  • Так далее...

И, возможно, на нескольких языках. На сегодняшний день Shutterstock разработал базовые списки грязных слов на 10 языках, но он по-прежнему является базовым и в значительной степени ориентирован на их нужды в тегировании. Есть ряд других списков, доступных в Интернете.

Я согласен с принятым ответом, что это не определенная наука, и, поскольку язык - это постоянно развивающаяся проблема, но проблема, когда коэффициент вылова составляет 90%, лучше, чем 0%. Это зависит исключительно от ваших целей - что вы пытаетесь достичь, уровень поддержки и насколько важно удалить ненормативную лексику разных типов.

При построении фильтра необходимо учитывать следующие элементы и их связь с вашим проектом:

  • Слова / фразы
  • Сокращения (FOAD/LMFAO и т. Д.)
  • Ложные срабатывания (слова, места и имена, такие как "мишит", "скунторп" и "титсворт")
  • URL-адрес (порносайты являются очевидной мишенью)
  • Личная информация (электронная почта, адрес, телефон и т. Д. - если применимо)
  • Выбор языка (обычно английский по умолчанию)
  • Модерация (как, если вообще, вы можете взаимодействовать с пользовательским контентом и что вы можете с ним делать)

Вы можете легко создать фильтр ненормативной лексики, который фиксирует более 90% ненормативной лексики, но вы никогда не достигнете 100%. Это просто невозможно. Чем ближе вы хотите приблизиться к 100%, тем сложнее становится... Создав в прошлом сложный механизм ненормативной лексики, который обрабатывал более 500 тыс. Сообщений в режиме реального времени в день, я бы предложил следующий совет:

Базовый фильтр будет включать:

  • Составление списка применимых ненормативной лексики
  • Разработка метода борьбы с ненормативной лексикой

Умеренно сложный файлер будет включать (в дополнение к базовому фильтру):

  • Использование сложного сопоставления с образцом для работы с расширенными деривациями (с использованием расширенного регулярного выражения)
  • Работа с Leetspeak (l33t)
  • Работа с ложными срабатываниями

Сложный фильтр будет включать в себя ряд следующих (в дополнение к умеренному фильтру):

  • Белые и черные списки
  • Наивная байесовская фильтрация фраз / терминов
  • Функции Soundex (где слово звучит как другое)
  • Расстояние Левенштейна
  • Морфологический
  • Модераторы-люди, помогающие руководить фильтрующим механизмом, чтобы учиться на собственном примере или там, где совпадения недостаточно точны без руководства (система самосовершенствования / непрерывного совершенствования)
  • Возможно какая-то форма ИИ движка

Я не знаю каких-либо хороших библиотек для этого, но что бы вы ни делали, убедитесь, что вы ошибаетесь в направлении пропуска вещей. Я имел дело с системами, которые не позволяют мне использовать "mpassell" в качестве имени пользователя, потому что он содержит "ass" в качестве подстроки. Это отличный способ оттолкнуть пользователей!

Система фильтрации ненормативной лексики никогда не будет идеальной, даже если программист вздрогнет и будет в курсе всех ню событий

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

Итак, единственное практическое решение двоякое:

  1. будьте готовы регулярно обновлять свой словарь
  2. нанять редактора-человека для исправления ложных срабатываний (например, "clbuttic" вместо "классических") и ложных отрицаний (ой! пропустил один!)

Во время моего рабочего собеседования технический директор компании, который брал у меня интервью, попробовал создать словесную веб-игру, которую я написал на Java. Из списка слов всего Оксфордского словаря английского языка, какое было первое слово, которое было предложено угадать?

Конечно, самое грязное слово в английском языке.

Так или иначе, я все еще получил предложение о работе, но затем я отследил список ненормативной лексики (не похожий на этот) и написал быстрый скрипт для генерации нового словаря без всех плохих слов (даже без просмотра списка).,

Для вашего конкретного случая, я думаю, что сравнение поиска с реальными словами звучит как способ составить список слов, подобный этому. Альтернативные стили / знаки препинания требуют немного больше работы, но я сомневаюсь, что пользователи будут использовать это достаточно часто, чтобы стать проблемой.

Единственный способ предотвратить оскорбительный ввод пользователя - запретить весь ввод пользователя.

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

Я собрал 2200 плохих слов на 12 языках: en, ar, cs, da, de, eo, es, fa, fi, fr, hi, hu, it, ja, ko, nl, no, pl, pt, ru, sv th, tlh, tr, zh.

Доступны опции MySQL dump, JSON, XML или CSV.

https://github.com/turalus/openDB

Я бы посоветовал вам выполнить этот SQL в вашей БД и проверять каждый раз, когда пользователь что-то вводит.

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

Один текущий пример этого: ebay использует словарный подход для фильтрации "плохих слов" из обратной связи. Если вы попытаетесь ввести немецкий перевод "это была совершенная транзакция" ("das war eine perfekte Transaktion"), ebay отклонит отзыв из-за плохих слов.

Зачем? Потому что немецкое слово "был" - это "война", а "война" в словаре "плохих слов" на ebay.

Так что остерегайтесь вопросов локализации.

Что касается подвопроса "обмануть систему", вы можете справиться с этим, нормализуя как список "плохих слов", так и введенный пользователем текст перед выполнением поиска. Например, используйте серию регулярных выражений (или tr, если он есть у PHP), чтобы преобразовать [z$5] в "s", [4 @] в "a" и т. д., затем сравните нормализованный список "плохих слов" с нормализованным текст. Обратите внимание, что нормализация потенциально может привести к дополнительным ложным срабатываниям, хотя в настоящий момент я не могу вспомнить ни одного фактического случая.

Более сложная задача состоит в том, чтобы придумать что-то, что позволит людям цитировать " ручка сильнее меча" и блокировать "пенис".

Если вы можете сделать что-то вроде Digg/Stackru, где пользователи могут понизить / пометить непристойный контент... сделайте это.

Тогда все, что вам нужно сделать, это проверить "непослушных" пользователей и заблокировать их, если они нарушают правила.

Также в конце игры, но проводил некоторые исследования и наткнулся здесь. Как уже упоминали другие, это почти почти невозможно, если бы это было автоматизировано, но если ваш дизайн / требование может включать в некоторых случаях (но не всегда) человеческие взаимодействия, чтобы проверить, является ли это нечестным или нет, вы можете рассмотреть ОД. https://docs.microsoft.com/en-us/azure/cognitive-services/content-moderator/text-moderation-api - мой текущий выбор по нескольким причинам:

  • Поддерживает много локализации
  • Они продолжают обновлять базу данных, поэтому мне не нужно идти в ногу с последними сленгами или языками (проблема обслуживания)
  • Когда есть высокая вероятность (т.е. 90% или более), вы можете просто отрицать это
  • Вы можете наблюдать за категорией, которая вызывает флаг, который может быть или не быть ненормативной лексикой, и может попросить кого-нибудь просмотреть его, чтобы узнать, что он является или не профан.

Для моих нужд это было / основано на общедоступном коммерческом сервисе (ОК, видеоигры), который другие пользователи могут / будут видеть имя пользователя, но дизайн требует, чтобы ему пришлось пройти фильтр ненормативной лексики, чтобы отклонить оскорбительное имя пользователя. Грустная часть этого вопроса в том, что классическая проблема "clbuttic", скорее всего, возникнет, поскольку имена пользователей, как правило, состоят из одного слова (до N символов), иногда объединяющего несколько слов… Опять же, когнитивная служба Microsoft не будет помечать "Assist" как текст.HasProfanity=true, но может указывать высокую вероятность одной из категорий.

Когда ОП запрашивает, как насчет "$$", вот результат, когда я пропустил его через фильтр: Как вы можете видеть, он определил, что он не светский, но он имеет высокую вероятность того, что это так, и помечается как рекомендации по рассмотрению (человеческое взаимодействие).

Когда вероятность высока, я могу либо вернуться назад: "Извините, это имя уже занято" (даже если это не так), чтобы оно было менее оскорбительным для лиц, не занимающихся цензурой, или что-то еще, если мы не хотим чтобы интегрировать обзор людей или вернуть "Ваше имя пользователя было уведомлено в оперативном отделе эксплуатации, вы можете подождать, пока ваше имя пользователя будет проверено и одобрено, или выбрать другое имя пользователя". Или что угодно...

Кстати, цена / цена на эту услугу для моей цели довольно низкая (как часто меняется имя пользователя?), Но, опять же, для OP, возможно, дизайн требует более интенсивных запросов и, возможно, не идеален для оплаты / подписки на ML-сервисы, или не могут иметь обзор / взаимодействие с человеком. Все зависит от дизайна... Но если дизайн отвечает всем требованиям, возможно, это может быть решением OP.

Если интересно, могу перечислить минусы в комментарии в будущем.

Я немного опоздал на вечеринку, но у меня есть решение, которое может сработать для тех, кто читает это. Это в javascript вместо php, но есть веская причина для этого.

Полное раскрытие, я написал этот плагин...

В любом случае.

Подход, который я выбрал, заключается в том, чтобы позволить пользователю "согласиться" на их фильтрацию ненормативной лексики. В основном ненормативная лексика будет разрешена по умолчанию, но если мои пользователи не хотят читать ее, они не должны. Это также помогает с проблемой "l33t sp3@k".

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

Вот демо-страница
https://chaseflorell.github.io/jQuery.ProfanityFilter/demo/

<div id="foo">
    ass will fail but password will not
</div>

<script>
    // code:
    $('#foo').profanityFilter({
        customSwears: ['ass']
    });
</script>

результат

*** не удастся, но пароль не будет

Когда у вас есть хорошая таблица MYSQL с некоторыми плохими словами, которые вы хотите отфильтровать (я начал с одной из ссылок в этой теме), вы можете сделать что-то вроде этого:

$errors = array();  //Initialize error array (I use this with all my PHP form validations)

$SCREENNAME = mysql_real_escape_string($_POST['SCREENNAME']); //Escape the input data to prevent SQL injection when you query the profanity table.

$ProfanityCheckString = strtoupper($SCREENNAME); //Make the input string uppercase (so that 'BaDwOrD' is the same as 'BADWORD').  All your values in the profanity table will need to be UPPERCASE for this to work.

$ProfanityCheckString = preg_replace('/[_-]/','',$ProfanityCheckString); //I allow alphanumeric, underscores, and dashes...nothing else (I control this with PHP form validation).  Pull out non-alphanumeric characters so 'B-A-D-W-O-R-D' shows up as 'BADWORD'.

$ProfanityCheckString = preg_replace('/1/','I',$ProfanityCheckString); //Replace common numeric representations of letters so '84DW0RD' shows up as 'BADWORD'.

$ProfanityCheckString = preg_replace('/3/','E',$ProfanityCheckString);

$ProfanityCheckString = preg_replace('/4/','A',$ProfanityCheckString);

$ProfanityCheckString = preg_replace('/5/','S',$ProfanityCheckString);

$ProfanityCheckString = preg_replace('/6/','G',$ProfanityCheckString);

$ProfanityCheckString = preg_replace('/7/','T',$ProfanityCheckString);

$ProfanityCheckString = preg_replace('/8/','B',$ProfanityCheckString);

$ProfanityCheckString = preg_replace('/0/','O',$ProfanityCheckString); //Replace ZERO's with O's (Capital letter o's).

$ProfanityCheckString = preg_replace('/Z/','S',$ProfanityCheckString); //Replace Z's with S's, another common substitution.  Make sure you replace Z's with S's in your profanity database for this to work properly.  Same with all the numbers too--having S3X7 in your database won't work, since this code would render that string as 'SEXY'.  The profanity table should have the "rendered" version of the bad words.

$CheckProfanity = mysql_query("SELECT * FROM DATABASE.TABLE p WHERE p.WORD = '".$ProfanityCheckString."'");
if(mysql_num_rows($CheckProfanity) > 0) {$errors[] = 'Please select another Screen Name.';} //Check your profanity table for the scrubbed input.  You could get real crazy using LIKE and wildcards, but I only want a simple profanity filter.

if (count($errors) > 0) {foreach($errors as $error) {$errorString .= "<span class='PHPError'>$error</span><br /><br />";} echo $errorString;} //Echo any PHP errors that come out of the validation, including any profanity flagging.


//You can also use these lines to troubleshoot.
//echo $ProfanityCheckString;
//echo "<br />";
//echo mysql_error();
//echo "<br />";

Я уверен, что есть более эффективный способ сделать все эти замены, но я не достаточно умен, чтобы понять это (и это, кажется, работает хорошо, хотя и неэффективно).

Я считаю, что вы должны ошибиться, если разрешите пользователям регистрироваться и использовать людей для фильтрации и добавления в таблицу ненормативной лексики по мере необходимости. Хотя все зависит от стоимости ложного срабатывания (хорошо помеченное как плохое слово) и ложного отрицания (плохое слово проходит). Это в конечном итоге должно определять, насколько вы агрессивны или консервативны в своей стратегии фильтрации.

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

Не. Это просто приводит к проблемам. Один из моих личных опытов с фильтрами ненормативной лексики - это время, когда меня выгнали / забанили на канале IRC за упоминание о том, что я "направляюсь через мост на Хэнкок на пару часов" или что-то в этом роде.

Я согласен с постом HanClinto выше в этой дискуссии. Я обычно использую регулярные выражения для совпадения строк входного текста. И это тщетное усилие, так как, как вы уже упоминали, вы должны явно учитывать все хитрые формы письма, популярные в сети, в вашем "заблокированном" списке.

С другой стороны, в то время как другие обсуждают этику цензуры, я должен согласиться с тем, что какая-то форма необходима в Интернете. Некоторым людям просто нравится публиковать вульгарность, потому что она может быть мгновенно оскорбительной для большого количества людей и абсолютно не требует размышлений со стороны автора.

Спасибо за идеи.

Правила HanClinto!

Честно говоря, я бы позволил им вывести слова "обмануть систему" ​​и запретить их, а это только я. Но это также упрощает программирование.

Что я хотел бы сделать, это реализовать фильтр регулярных выражений, например, так: /[\s]dooby (doo?)[\s]/i или это слово стоит перед другими, /[\s]doob(er|ed|est)[\s]/, Это предотвратит фильтрацию слов, таких как предикат, что вполне допустимо, но также потребует знания других вариантов и обновления фактического фильтра, если вы изучите новый. Очевидно, что это все примеры, но вам придется решить, как сделать это самостоятельно.

Я не собираюсь печатать все слова, которые я знаю, не тогда, когда я на самом деле не хочу их знать.

Я согласен с тщетностью предмета, но если вам нужен фильтр, посмотрите самшит Нина:

Boxwood - это расширение PHP для быстрой замены нескольких слов в тексте. Он поддерживает регистрозависимое и регистрозависимое сопоставление. Требуется, чтобы текст, с которым он работает, был закодирован как UTF-8.

Также см. Этот блог для более подробной информации:

С Boxwood вы можете сделать так, чтобы ваш список поисковых терминов был настолько длинным, насколько вам нужно - алгоритм поиска и замены не становится медленнее с большим количеством слов в списке слов для поиска. Он работает путем создания трех всех поисковых терминов, а затем сканирует текст вашего предмета только один раз, просматривая элементы этого дерева и сравнивая их с символами в вашем тексте. Он поддерживает US-ASCII и UTF-8, регистрозависимое или нечувствительное сопоставление и имеет некоторую логику проверки границ слов, ориентированную на английский язык.

Я пришел к выводу, что для создания хорошего фильтра ненормативной лексики нам нужно 3 основных компонента, или, по крайней мере, это то, что я собираюсь сделать. Это они:

  1. Фильтр: фоновый сервис, который проверяет черный список, словарь или что-то в этом роде.
  2. Не разрешать анонимный аккаунт
  3. Сообщить о нарушении

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

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

Ловить слова

Скажем так, вы хотите поймать F-Word. Легко, правда? Ну посмотрим.

Вы можете перебрать строку, чтобы найти "ебать". К сожалению, в наши дни люди применяют фильтры. Фильтр ненормативной лексики не улавливал "fuk".

Можно попытаться проверить наличие нескольких вариантов написания и вариантов слова, но это снизит производительность вашего кода. Чтобы поймать F-Word, вам нужно искать "fuc", "Fuc", "fuk", "Fuk", "F***" и т. Д. И этот список можно продолжать и продолжать.

Избежание невинности

Итак, как насчет того, чтобы сделать его без учета регистра и игнорировать пробелы, чтобы он ловил "F u C k"? Это может звучать как хорошая идея, но кто-то может просто обойти фильтр ненормативной лексики с "FUCK"

Вы игнорируете пунктуацию.

Теперь это реальная проблема, так как предложение типа "Черт возьми! будет воспринимать как "ад" и "какзадницу?" воспринимает как "задницу"

И есть несколько слов, которые вы должны исключить из фильтра, такие как "Заголовок", потому что в нем есть "синица".

Люди могут также использовать замещающие слова, такие как "Frack". Вы тоже это блокируете? А как насчет "ручка" для "пенис"? Ваша программа не имеет искусственного интеллекта, чтобы знать, хороша ли строка или нет.

Не используйте ненормативную лексику.Их трудно развивать, и они так же медленны, как ползать.

Не.

Так как:

  • Clbuttic
  • Ненормативная лексика это не OMG EVIL
  • Ненормативная лексика не может быть эффективно определена
  • Большинство людей, скорее всего, не ценят "защиту" от ненормативной лексики

Изменить: Хотя я согласен с комментатором, который сказал, что "цензура не так", это не характер этого ответа.

Другие вопросы по тегам