Пишем собственный лапшесниматель
easy

Пишем собственный лапшесниматель

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

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

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

Что делаем

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

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

Инструменты

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

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

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

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

  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>

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

Что дальше

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

Идея:

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

Текст и код:

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

Редактор:

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

Художник:

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

Корректор:

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

Вёрстка:

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

Соцсети:

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

Получите ИТ-профессию
В «Яндекс Практикуме» можно стать разработчиком, тестировщиком, аналитиком и менеджером цифровых продуктов. Первая часть обучения всегда бесплатная, чтобы попробовать и найти то, что вам по душе. Дальше — программы трудоустройства.
Начать карьеру в ИТ
Получите ИТ-профессию Получите ИТ-профессию Получите ИТ-профессию Получите ИТ-профессию
Еще по теме
easy