Пишем собственный лапшесниматель
Пишем собственный лапшесниматель
Подсвечиваем манипуляции и пропаганду на любом сайте

В интер­не­те мно­го инфор­ма­ции, кото­рая может навре­дить вам и вашим близ­ким: про­па­ган­да и контр­про­па­ган­да, кур­сы вол­шеб­но­го инве­сти­ро­ва­ния и бинар­ные опци­о­ны; тео­рии заго­во­ра и пси­хо­нав­ти­ка. Вы умные и види­те мани­пу­ля­ции насквозь, но как насчёт ваших дру­зей, зна­ко­мых и осо­бен­но — детей? 

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

Что делаем

Мы отбе­рём сло­ва, кото­рые наи­бо­лее харак­тер­ны для мошен­ни­ков, про­во­ка­то­ров, про­па­ган­ди­стов и мани­пу­ля­то­ров. Далее напи­шем скрипт, кото­рый под­све­тит на стра­ни­це эти сло­ва в раз­ных фор­мах. Когда вы буде­те запус­кать этот скрипт на дру­гих стра­ни­цах, он будет под­све­чи­вать все опас­ные сло­ва и обра­щать на них вни­ма­ние. Чита­тель будет видеть, что им мани­пу­ли­ру­ют, и при­мет взве­шен­ное реше­ние, что делать дальше. 

Что­бы было про­ще тести­ро­вать и отла­жи­вать скрипт, мы зара­нее напи­шем текст и будем вызы­вать скрипт на этой же стра­ни­це. Даль­ше мы при­ду­ма­ем, как пере­не­сти это на любую дру­гую стра­ни­цу в интернете.

Инструменты

Пра­ви­ло хоро­ше­го про­грам­ми­ста — исполь­зуй свой рабо­чий код в дру­гих про­ек­тах, что­бы сэко­но­мить время. 

У нас есть про­ект, в кото­ром мы дела­ли поиск по стра­ни­це с под­свет­кой. Рабо­та­ет так: вво­дим сло­во, а скрипт под­све­чи­ва­ет все най­ден­ные сло­ва. Минус тако­го под­хо­да в том, что поиск рабо­та­ет толь­ко по одно­му сло­ву, а нам нуж­но искать несколь­ко слов одновременно.

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

Логика работы

  1. Берём гото­вую стра­ни­цу из про­ек­та с поис­ком на jQuery.
  2. Уда­ля­ем из неё всё то, что мы не будем использовать.
  3. Берём регу­ляр­ные выра­же­ния и про­пи­сы­ва­ем в них слова-триггеры, кото­рые нуж­но будет найти.
  4. Пере­би­ра­ем весь текст на стра­ни­це с помо­щью регу­ляр­ных выра­же­ний и под­све­чи­ва­ем совпадения.
  5. Для под­свет­ки исполь­зу­ем нара­бот­ки из про­ек­та с API и сер­ви­сом «Главред» — там мы тоже выде­ля­ли целые сло­ва в тексте.

Готовим страницу

Берём гото­вую стра­ни­цу из про­ек­та с поис­ком и остав­ля­ем на ней толь­ко текст, стиль под­свет­ки и нача­ло скрип­та. Заод­но немно­го поме­ня­ем текст, что­бы было на чём потренироваться.

<html>
<!-- служебная часть -->

<head>
  <!-- заголовок страницы -->
  <title>Поиск на странице</title>
  <!-- настраиваем служебную информацию для браузеров -->
  <meta charset="utf-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <meta name="viewport" content="width=device-width, initial-scale=1">
  <!-- задаём CSS-стили прямо здесь же, чтобы всё было в одном файле -->
  <style type="text/css">

    /* выбираем цвет подсветки — светло-зелёный*/
    .highlight {
      background: #4CFF00;
    }

  </style>
  <!-- закрываем служебную часть страницы -->
</head>
<!-- началось содержимое страницы -->

<body>
 
  <!-- подключаем библиотеку jQuery -->
  <script src="https://thecode.media/wp-content/uploads/2019/06/jquery.js" type="text/javascript"></script>
  <!-- подключаем к ней плагин highlight.js -->
  <script src='https://thecode.media/wp-content/uploads/2019/06/jqueryhighlight.js' />
  </script>
  <!-- говорим браузеру, что сейчас начнётся скрипт -->
  <script type="text/javascript">

    // когда документ загрузился — начинаем работу
    $(document).ready(function () {

  });
  </script>
  
  <!-- в этом блоке разместим наш основной текст -->
  <div class="content">
    <p>
      Достаточно всего 5 минут в день, чтобы лучше понять, как работают библиотеки и плагины в веб-программировании. Вместо того, чтобы работать «на дядю», давайте с их помощью сделаем удобный
      поиск по странице прямо сейчас. Мы знаем, что современные браузеры тоже умеют это делать, но мы сделаем свою версию, которая
      работает не хуже, чем в Хроме или Сафари. Это поможет вам работать где хотите.
    <p>
    <h2>Общая идея</h2>
    </p>
    <p>
      У нас есть сайт с неким текстом, и нам нужно быстро находить в нём нужные слова или части слов. Для этого мы в
      самом начале страницы делаем поле ввода, куда будем писать наши слова для поиска, и кнопку, которая этот поиск
      запускает. Это поможет нам быстро заработать большие деньги, когда мы подключим криптографию и уедем на Бали или на Таиланд. Это и будет ваш пассивный доход.
    </p>
    <p>
      Дальше скрипт берёт весь текст, находит в нём нужные фрагменты и подсвечивает их, заставляя нас горбатиться сверх меры. Если он ничего не находит —
      пишет сообщение о том, что таких слов в тексте нет. Но системе выгодно, чтобы поиск ничего не находил, потому что иначе вы бы смогли в любое время работать в декрете.
    </p>
  </div>
  <!-- закончилось содержимое страницы -->
</body>
<!-- конец всего HTML-документа -->

</html>
Пишем собственный лапшесниматель Пока ниче­го не про­ис­хо­дит, виден толь­ко текст 

Пишем регулярные выражения

Давай­те най­дём в тек­сте все «про­да­ю­щие» сло­ва, кото­рые, как дума­ет автор, дела­ют текст более цеп­ля­ю­щим и застав­ля­ют верить в происходящее. 

Для нача­ла соста­вим неболь­шой спи­сок мани­пу­ля­тор­ских выражений:

  • боль­шие деньги
  • рабо­таю где хочу
  • пря­мо сейчас
  • рабо­тать «на дядю»
  • гор­ба­тить­ся
  • в любое время
  • все­го Х минут в день
  • крипто-
  • пас­сив­ный доход / заработок
  • луч­шая жизнь
  • на Бали
  • Таи­ланд
  • систе­ме выгодно
  • рабо­та в декрете

Его мож­но про­дол­жать ещё дол­го, сей­час глав­ное понять принцип. 

👉 На самом деле в таких сло­вах нет ниче­го пло­хо­го — это про­сто сло­ва. В дру­гом кон­тек­сте они бы не вызы­ва­ли таких эмо­ций, пото­му что выра­жа­ли бы пра­виль­ную мысль. 

Напри­мер, когда пле­мян­ник на кани­ку­лах идёт рабо­тать к мами­но­му бра­ту, он в бук­валь­ном смыс­ле рабо­та­ет на дядю. Но как толь­ко мы встре­ча­ем «рабо­тать „на дядю“» в нега­тив­ном кон­тек­сте, а рядом пред­ла­га­ет­ся стать финан­со­во неза­ви­си­мым с помо­щью бинар­ных опци­о­нов — ско­рее все­го, это манипуляция. 

Теперь каж­дое выра­же­ние пре­вра­ща­ем в регу­ляр­ное на JavaScript и встав­ля­ем в самое нача­ло скрип­та на странице.

Регулярные выражения

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

У регу­ля­рок есть две прин­ци­пи­аль­ные части: сами бук­вы, по кото­рым ищем, и токе­ны. Напри­мер, если мы хотим най­ти в тек­сте сло­во «сво­бо­да», то регу­ляр­ка будет выгля­деть так:

свобода

Но если мы хотим, что­бы в тек­сте нашлись сло­ва «сво­бо­да» и «сво­бо­ды», мы долж­ны будем заме­нить одну из букв на токен, кото­рый обо­зна­ча­ет бук­ву. Это токен \w:

свобод\w

Если мы хотим раз­ре­шить нахо­дить сло­ва в дру­гих паде­жах типа «сво­бода», «сво­бод» «сво­бо­да­ми», мы долж­ны раз­ре­шить токе­ну \w повто­рять­ся от 0 до 3 раз:

свобод\w{0,3}

А если мы не хотим, что­бы поиск нахо­дил сло­во «несво­бо­да», нуж­но ска­зать, что «сво­бод» долж­но начи­нать­ся в нача­ле сло­ва. Для это­го есть токен \b, кото­рый озна­ча­ет гра­ни­цу сло­ва. Поста­вим его с двух сто­рон, что­бы поиск не нахо­дил сло­ва типа «сво­бо­до­лю­би­вый» и «сво­бо­до­не­на­вист­ни­че­ство».

\bсвобод\w{0,3}\b

Это закли­на­ние пере­во­дит­ся так: «В нача­ле сло­ва най­ти бук­вы с-в-о-б-о-д, а потом от нуля до трёх любых букв, и потом дол­жен сра­зу быть конец слова». 

Это закли­на­ние сра­бо­та­ет в любом язы­ке, кро­ме JavaScript, пото­му что JS не счи­та­ет рус­ские бук­вы за сло­во­об­ра­зу­ю­щие сим­во­лы. При­дёт­ся исполь­зо­вать дру­гие токе­ны, кото­рые реша­ют эту проблему:

\Bсвобод\W{0,3}\B

Токе­ны \B и \W — это уже дру­гие токе­ны: в регу­ляр­ках регистр важен. Такой вот костыль JavaScript. В Python или InDesign этой про­бле­мы нет.

Так­же в JavaScript регу­ляр­ку нуж­но обхва­ты­вать косы­ми чертами /.../.

// массив с регулярными выражениями
var r = [];
// заполняем элементы массива нашими выражениями
r[0] = /\B[бБ]ольш\W{2,4} +деньг\W{1,3}\B/;
r[1] = /\Bработа\W{1,4}где хо\W{2,7}\B/;
r[2] = /\B[пП]рямо сейчас\B/;
r[3] = /\B[рР]абота\W{0,3} ["«]на дядю["»]\B/;
r[4] = /\B[Гг]орба\W{2,6}с[яь]\B/;
r[5] = /\B[вВ] любое время\B/;
r[6] = /\Bвсего +\d{1,3} +(минут|час)\D{0,3} в (день|неделю)\B/;
r[7] = /\B[кК]рипто\W\B/;
r[8] = /\B[пП]ассивн\W{1,3}\B/;
r[9] = /\B[нН]а +Бали\B/;
r[10] = /\BТа[ий]ланд\W{0,2}\B/;
r[11] = /\B[сС]истем\W{1,3} выгодно\B/;
r[12] = /\B[рР]абот\W{1,3} в декрете\B/;

Находим совпадения на странице

Так как у нас весь текст нахо­дит­ся внут­ри абза­цев, поме­чен­ных тегом <p>, то с помо­щью jQuery мы пере­бе­рём все эле­мен­ты на стра­ни­це с таким тегом и обра­бо­та­ем их содержимое.

Что­бы под­све­тить нуж­ный текст, исполь­зу­ем тег <span> — мы так уже дела­ли, когда под­клю­ча­ли API сер­ви­са «Главред» к орфо­кор­рек­то­ру.

Каж­дый абзац будем обра­ба­ты­вать так:

  1. Берём содер­жи­мое абзаца.
  2. Смот­рим, сколь­ко регу­ляр­ных выра­же­ний запи­са­но у нас в массиве.
  3. По оче­ре­ди нахо­дим в тек­сте абза­ца сов­па­де­ния по каж­дой регу­ляр­ке и обо­ра­чи­ва­ем сов­па­де­ние тегом <span>.

Запи­шем это на язы­ке JavaScript. Обра­ти­те вни­ма­ние на послед­нюю строч­ку — мы исполь­зу­ем вызов функ­ции highlightText(), кото­рой у нас ещё нет. В сле­ду­ю­щем раз­де­ле мы это исправим.

// функция, которая подсвечивает текст в содержимом какого-то элемента на странице
      function lst(txt) {
    
        // перебираем по очереди все абзацы, которые есть на странице, используя возможности jQuery
        $(txt).each(function () {

          // по очереди проходим по массиву с регулярными выражениями
          for ( var z = 0; z < r.length; z++) {
            // на каждом шаге цикла берём содержимое очередного абзаца 
            var par = this.innerHTML;
            // и прогоняем его через подсветку каждого найденного регулярного выражения
            this.innerHTML = highlightText(r[z],par);
          }
        });
    };
   // подсвечиваем все слова внутри абзацев на странице
    lst('p');

Подсвечиваем текст

Послед­нее, что нам оста­лось доба­вить в скрипт, — функ­цию под­свет­ки highlightText(), кото­рую мы исполь­зо­ва­ли в преды­ду­щем фраг­мен­те кода.

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

Глав­ная слож­ность — выце­пить из сра­бо­тав­шей регу­ляр­ки кон­крет­ный текст, по кото­ро­му было сов­па­де­ние. Это нам нуж­но для того, что­бы заме­нить най­ден­ный фраг­мент на фраг­мент с тега­ми вокруг тек­ста. Для это­го пой­дём на хитрость.

  1. У нас есть стан­дарт­ная функ­ция JavaScript под назва­ни­ем replace(). Имен­но она нахо­дит нам текст по шаб­ло­ну и заме­ня­ет на какой-то другой. 
  2. replace() тре­бу­ет двух пара­мет­ров: что най­ти и на что заме­нить. Нахо­дить мы будем по регу­ляр­ным выра­же­ни­ям. А вот с заме­ной про­бле­ма: мы же не зна­ем, какую имен­но сло­во­фор­му нашла наша регу­ляр­ка. А ска­зать, на что заме­нить, нуж­но однозначно. 
  3. Что­бы обой­ти это огра­ни­че­ние, мы сно­ва вызо­вем эту же функ­цию replace(), но со встро­ен­ным пара­мет­ром match. Если пере­ве­сти на рус­ский, то полу­чит­ся так:

Функ­цияЧто най­тиНа что заменить
replace(new RegExp(regular, "gi")function replace(match {
        return '<span class="highlight">' + match + '</span>';

    }
);
заме­ни(То, что ты най­дёшь по нашей регу­ляр­ке, кото­рую ты полу­чи­ла на вход. gi озна­ча­ет, что искать нуж­но все встре­ча­ю­щи­е­ся сло­ва и игно­ри­ро­вать регистр.Най­ден­ная стро­ка будет хра­нить­ся в пере­мен­ной match. Возь­ми то, что в этой пере­мен­ной, обер­ни в <span> и вер­ни обрат­но в функ­цию replace как вто­рой пара­метр «на что заменить»);

Чест­но ска­жем: этот трюк с двой­ным вызо­вом мы ста­щи­ли у кол­лег. Как и все нор­маль­ные программисты. 

// функция, которая оборачивает найденное регулярное выражение в тег с подсветкой
// в качестве аргументов мы передаём регулярное выражение и текст, который нужно обработать
function highlightText(regular, originalHtml) {
    // переменная, в которую мы поместим итоговое значение
    var newHtml;
    // оборачиваем найденное значение в тег <span>
    // решение подсмотрели здесь: https://www.telerik.com/support/kb/aspnet-ajax/details/highlight-text-inside-html-elements-and-templates
    newHtml = originalHtml.replace(new RegExp(regular, "gi"), function replace(match) {
        return '<span class="highlight">' + match + '</span>';
    })
    // возвращаем результат обработки
    return newHtml;
}

Соби­ра­ем всё в один файл и смот­рим резуль­тат:

Готовый код

<html>
<!-- служебная часть -->

<head>
  <!-- заголовок страницы -->
  <title>Поиск на странице</title>
  <!-- настраиваем служебную информацию для браузеров -->
  <meta charset="utf-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <meta name="viewport" content="width=device-width, initial-scale=1">
  <!-- задаём CSS-стили прямо здесь же, чтобы всё было в одном файле -->
  <style type="text/css">

    /* выбираем цвет подсветки — светло-зелёный*/
    .highlight {
      background: #4CFF00;
    }


  </style>
  <!-- закрываем служебную часть страницы -->
</head>
<!-- началось содержимое страницы -->

<body>
 
  <!-- подключаем библиотеку jQuery -->
  <script src="https://thecode.media/wp-content/uploads/2019/06/jquery.js" type="text/javascript"></script>
  <!-- подключаем к ней плагин highlight.js -->
  <script src='https://thecode.media/wp-content/uploads/2019/06/jqueryhighlight.js' />
  </script>
  <!-- говорим браузеру, что сейчас начнётся скрипт -->
  <script type="text/javascript">

    // массив с регулярными выражениями
    var r = [];
    // заполняем элементы массива нашими выражениями
    r[0] = /\B[бБ]ольш\W{2,4} +деньг\W{1,3}\B/;
    r[1] = /\Bработа\W{1,4}где хо\W{2,7}\B/;
    r[2] = /\B[пП]рямо сейчас\B/;
    r[3] = /\B[рР]абота\W{0,3} ["«]на дядю["»]\B/;
    r[4] = /\Bгорба\W{2,6}с[яь]\B/;
    r[5] = /\B[вВ] любое время\B/;
    r[6] = /\Bвсего +\d{1,3} +(минут|час)\D{0,3} в (день|неделю)\B/;
    r[7] = /\B[кК]рипто\W\B/;
    r[8] = /\B[пП]ассивн\W{1,3}\B/;
    r[9] = /\B[нН]а +Бали\B/;
    r[10] = /\BТаиланд\W{0,2}\B/;
    r[11] = /\B[сС]истем\W{1,3} выгодно\B/;
    r[12] = /\B[рР]абот\W{1,3} в декрете\B/;
  
    

    // когда документ загрузился — начинаем работу
    $(document).ready(function () {

      // функция, которая оборачивает найденное регулярное выражение в тег с подсветкой
      // в качестве аргументов мы передаём регулярное выражение и текст, который нужно обработать
      function highlightText(regular, originalHtml) {
          // переменная, в которую мы поместим итоговое значение
          var newHtml;
          // оборачиваем найденное значение в тег <span>
          // решение подсмотрели здесь: https://www.telerik.com/support/kb/aspnet-ajax/details/highlight-text-inside-html-elements-and-templates
          newHtml = originalHtml.replace(new RegExp(regular, "gi"), function replace(match) {
              return '<span class="highlight">' + match + '</span>';
          })
          // возвращаем результат обработки
          return newHtml;
      }

     // функция, которая подсвечивает текст в содержимом какого-то элемента на странице
      function lst(txt) {
    
        // перебираем по очереди все абзацы, которые есть на странице, используя возможности jQuery
        $(txt).each(function () {

          // по очереди проходим по массиву с регулярными выражениями
          for ( var z = 0; z < r.length; z++) {
            // на каждом шаге цикла берём содержимое очередного абзаца 
            var par = this.innerHTML;
            // и прогоняем его через подсветку каждого найденного регулярного выражения
            this.innerHTML = highlightText(r[z],par);
          }
        });
    };
    // подсвечиваем все слова внутри абзацев на странице
    lst('p');


  });
  </script>
  
  <!-- в этом блоке разместим наш основной текст -->
  <div class="content">
    <p>
      Достаточно всего 5 минут в день, чтобы лучше понять, как работают библиотеки и плагины в веб-программировании. Вместо того, чтобы работать «на дядю», давайте с их помощью сделаем удобный
      поиск по странице прямо сейчас. Мы знаем, что современные браузеры тоже умеют это делать, но мы сделаем свою версию, которая
      работает не хуже, чем в Хроме или Сафари. Это поможет вам работать где хотите.
    <p>
    <h2>Общая идея</h2>
    </p>
    <p>
      У нас есть сайт с неким текстом, и нам нужно быстро находить в нём нужные слова или части слов. Для этого мы в
      самом начале страницы делаем поле ввода, куда будем писать наши слова для поиска, и кнопку, которая этот поиск
      запускает. Это поможет нам быстро заработать большие деньги, когда мы подключим криптографию и уедем на Бали или на Таиланд. Это и будет ваш пассивный доход.
    </p>
    <p>
      Дальше скрипт берёт весь текст, находит в нём нужные фрагменты и подсвечивает их, заставляя нас горбатиться сверх меры. Если он ничего не находит —
      пишет сообщение о том, что таких слов в тексте нет. Но системе выгодно, чтобы поиск ничего не находил, потому что иначе вы бы смогли в любое время работать в декрете.
    </p>
  </div>
  <!-- закончилось содержимое страницы -->
</body>
<!-- конец всего HTML-документа -->

</html>

Сра­зу вид­но, что автор силь­но хочет нам что-то про­дать, поэто­му исполь­зу­ет такие слова. 

Что дальше

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

Идея:

Мак­сим Ильяхов

Текст и код:

Миха­ил Полянин

Редак­тор:

Мак­сим Ильяхов

Худож­ник:

Даня Бер­ков­ский

Кор­рек­тор:

Ири­на Михеева

Вёрст­ка:

Мария Дро­но­ва

Соц­се­ти:

Олег Веш­кур­цев