Wyrażenie regularne a wulgaryzmy

0

Witam,

Ma ktoś pomysł jak ugryźć wycinanie wulgaryzmów np. w formularzach na stronach ? Chodzi o coś lepszego niż str_replace, które można łatwo oszukać.

Np: zakazanym słowem niech będzie PROGRAMISTA .

P$ogramista
Programist(a)
pr ogramista
_programista

Jest wiele możliwości obejścia filtru - w konkretnym wypadku oczywiście niecenzuralne słowa, ale nie będę ich tu używał. Czy da się to jakoś skutecznie wycinać mimo stosowania przez użytkownika przykładowych chwytów jak zastępowanie literek innymi znakami albo dzielenie słowa spacjami ... ?

0

To co pokazałeś jest jak najbardziej możliwe. Widziałem większe cuda robione regexem przez mojego kolegę, którego mogę nazwać geniuszem regexów. Ja niestety nic więcej nie powiem oprócz tego że są osoby co coś takiego są w stanie wykryć w 99%.

0

Proponuję wyjść od ogółu do szczegółu.

Cel: Chcesz, aby wulgaryzmy w tekście były ocenzurowane.
Innymi słowy - potrzebujesz mechanizm, który na wejściu dostanie tekst do ocenzurowania i kryteria cenzurowania, a na wyjściu zwróci ocenzurowany tekst.

Kryteria cenzurowania:

Napisałeś że chcesz, aby mechanizm prócz cenzurowania dosłownego, radził sobie ze wstawkami różnych znaków, zamianami liter na inne znaki podobne graficznie w cenzurowanych słowach.
Przeanalizujmy te kryterium:

Patrząc na Twój przykład zauważyłem 3 sposoby obejścia zabezpiecznia:

  1. zamiana znaków na odpowiedniki graficzne np "s" na "$", "i" na "!" itd
  2. dopisanie różnego rodzaju przedrostków i przyrostków, np " ", "_", "(", ")"
  3. zamiana wielkości liter

W takim razie Twoje kryteria cenzurowania mogą się składać z następujących elementów:

  • lista wulgaryzmów
  • lista znaków, które mogą być przedrostkami i/lub przyrostkami
    Dodatkowo, mechanizm porównujący powinien ignorować wielkość liter

Myślę, że dla takiej definicji zadania będziesz w stanie napisać działające rozwiązanie.
W razie problemów pisz.

0

Ja kiedyś spotkałem się z takim mechanizmem, że gdy ktoś napisał wulgaryzm to od razu dostawał bana i nawet jak ktoś się skapnął, że jest taki filtr to już go obejść nie mógł na tym koncie.

No i zawsze była nie pewność czy aby na pewno dane słowo przejdzie przez filtr i przez to mniej osób ryzykowało.

0

Można spróbować podejść do tego trochę inaczej - sieci neuronowe. Można te. Sieci nauczyć rozpoznawania z jakimś prawdopodobieństwem wulgaryzmy. Będzie to bardziej uniwersalny sposób, bo jak będziesz chciał dopisać nowe słowo, to uczysz/sposob obejścia te sieć i juz następnym razem powinno to i podobne tricki zablokować

Problemem wg mnie jest kilka: szansę na false positive oraz większe wymagania od sprzętu (głównie ramu).

1

Nie ma sensu. To forum niby ma cenzurę: piszę
prostytutka (k u r w a) i cenzuruje.
piszę
c**** (ch u j) i cenzuruje
piszę
g**no (g ó w n o)

Ale już:
kur**wa
czy
ch**uj
nie ocenzuruje.
Widocznie twórcy skryptu do cenzury nie pomyśleli o przypadkach brzegowych...

Poza tym po poco cenzurować przekleństwa? Lepiej już cenzurować słowa typu Viagra, cialis, clonazepam, enlarge your penis czy inne sformułowania, które się pojawiają w spamie/tekstach pisanych przez boty, niż nie pozwalać normalnym użytkownikom przeklinać.

Poza tym jeśli ocenzurujesz słowo "c****" i zrobisz to źle, to słowa podsłuchuj też bedą ocenzurowane... (tutaj na szczęście zrobili to dobrze, ale już spotkałem się z sytuacjami, gdzie słowa podsłuchuj były ocenzurowane).

innymi słowy z automatami do cenzury jest tak, że albo masz dużo fałszywych pozytywów i są cenzurowane normalne słowa, albo masz automaty, które łatwo oszukać (albo i to, i to), więc jak ktoś już wspomniał - jest to walka z wiatrakami. Już lepiej ręcznie moderować wulgarnie wypowiedzi, jeśli się odczuwa taką potrzebę.

1

Krótko: nie da się czegoś takiego zrobić. Nawet najlepsze mechanizmy można bardzo łatwo obejść, sposobów jest co najmniej kilka.

Opcje są dwie, proste:

  • napisz w regulaminie, że nie wolno, zrób sobie powiadomienie na wulgaryzmy (dzięki nieużywaniu auto-cenzora ludzie nie będą kombinować i będą pisać bezpośrednio, co łatwo dzięki temu wykryjesz do powiadomień - pod warunkiem, że nie powiesz ludziom, że masz takie powiadomienia) i ładuj bany
  • niczego nie cenzuruj, chyba, że prowadzisz forum dla dzieci, dorośli ludzie nie używają wulgaryzmów bez potrzeby, a wulgaryzmy nie są złem nieczystym i używanie ich w rozsądnych granicach jest ok

Swoją drogą - czy wiesz, że zajebisty nie jest już wulgaryzmem, ale już zajebać dalej tak?

0

Nie wiem na ile to jest skuteczne:

vulgar.php (lista słów wulgarnych):

return array(
    'foo',
    'bar',
    'programista',
    'programistka',    
    // i dalej wszystkie znane wulgaryzmy, z ich odmianami 
);
function filter_vulgar($text, $replacement = '******')
{
    $words = include 'vulgar.php';
    $result = $text;
    foreach ($words as $word)
    {
        $pattern = '/' . $word . '/i';
        if (preg_match($pattern, $result, $matches))
        {
            $result = preg_replace($pattern, $replacement, $result);
        }
    }
    return $result;
}
1

Pomyślałem nad tym klika dni i wymyśliłem pewien algorytm.

Założenia (przykład dla cenzurowanego słowa "pupa"):

  1. cenzura ma działać, gdy litery są powielone: puuuuppa
  2. cenzura ma działać gdy zamiast liter są ich substytuty np [email protected]
  3. cenzura ma działać, gdy pomiędzy literami są jakieś separatory np p.u.p.a
  4. cenzura ma działać bez względu na wielkość liter np PuPa

Algorytm jest następujący:
Rozbijamy nasze cenzurowane słowo na tablicę liter: 'pupa' => ['p', 'u', 'p', 'a']
Dla każdej z liter tworzymy osobne wyrażenie regularne.
Tworzymy dodatkowe wyrażenie regularne definiujące separatory pomiędzy literami
Sklejamy ze sobą wszystkie wyrażenia regularne: naprzemiennie - wyr. regularne litery (w.r.) i wyr. regularne separatora (S)
i oznaczamy aby ignorował wielkość liter: 'pupa' => / (w.r. 'p') (S) (w.r. 'u') (S) (w.r. 'p') (S) (w.r. 'a') /i

Przykład dla litery - 'a':

  1. obsługa powieleń:
    "a" przekształcamy na "[a]+"

  2. obsługa substytutów:
    Załóżmy, że nasza definicja substytutów wygląda następująco:
    array(
    'a' => array('Q'),
    ...
    'u' => array('v')
    ...
    );

    Wówczas nasze przekształcenie będzie wyglądać tak:
    "[a]+" przekształcamy na "[a|Q]+"

  3. Obsługa separatorów:
    Załóżmy, że separatorami mogą być znaki '', '.' Wyrażenie regularne mogło by wyglądać tak: $separatorRegexp = [.]*
    Tablicę liter, którą zamieniliśmy w pkt 1 i 2 na tablicę wyrażeń regularnych należy złączyć w jeden string,
    a jako "kleju" użyć wyrażenia regularnego separatora z pkt 3 czyli:
    $regexp = implode(separatorRegexp, $arrayOfLetterPatterns)

  4. wielkość liter: $regexp = '/' . $regexp . '/i'

Oczywiście używamy preg_quote by nie rozwalić wyrażenia.

Napisałem przykładowy kod realizujący te zadanie:
https://github.com/Thommee/word-censor

Pozdr

1 użytkowników online, w tym zalogowanych: 0, gości: 1, botów: 0