В интернете много информации, которая может навредить вам и вашим близким: пропаганда и контрпропаганда, курсы волшебного инвестирования и бинарные опционы; теории заговора и психонавтика. Вы умные и видите манипуляции насквозь, но как насчёт ваших друзей, знакомых и особенно — детей?
Сегодня мы заложим основу для продукта, который поможет если не положить конец манипуляциям, то хотя бы усложнить работу манипуляторов. Дальше будем развивать продукт — подписывайтесь на нас в Телеграме, чтобы не пропустить.
Что делаем
Мы отберём слова, которые наиболее характерны для мошенников, провокаторов, пропагандистов и манипуляторов. Далее напишем скрипт, который подсветит на странице эти слова в разных формах. Когда вы будете запускать этот скрипт на других страницах, он будет подсвечивать все опасные слова и обращать на них внимание. Читатель будет видеть, что им манипулируют, и примет взвешенное решение, что делать дальше.
Чтобы было проще тестировать и отлаживать скрипт, мы заранее напишем текст и будем вызывать скрипт на этой же странице. Дальше мы придумаем, как перенести это на любую другую страницу в интернете.
Инструменты
Правило хорошего программиста — используй свой рабочий код в других проектах, чтобы сэкономить время.
У нас есть проект, в котором мы делали поиск по странице с подсветкой. Работает так: вводим слово, а скрипт подсвечивает все найденные слова. Минус такого подхода в том, что поиск работает только по одному слову, а нам нужно искать несколько слов одновременно.
С другой стороны, мы уже умеем работать с регулярными выражениями. С их помощью мы можем найти любое количество слов и словосочетаний на странице, даже с учётом склонений.
Логика работы
- Берём готовую страницу из проекта с поиском на jQuery.
- Удаляем из неё всё то, что мы не будем использовать.
- Берём регулярные выражения и прописываем в них слова-триггеры, которые нужно будет найти.
- Перебираем весь текст на странице с помощью регулярных выражений и подсвечиваем совпадения.
- Для подсветки используем наработки из проекта с 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 сервиса «Главред» к орфокорректору.
Каждый абзац будем обрабатывать так:
- Берём содержимое абзаца.
- Смотрим, сколько регулярных выражений записано у нас в массиве.
- По очереди находим в тексте абзаца совпадения по каждой регулярке и оборачиваем совпадение тегом <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(), которую мы использовали в предыдущем фрагменте кода.
Мы будем передавать функции два аргумента на вход: регулярное выражение и текст, который нужно обработать. Текст у нас уже есть, а регулярные выражения мы получаем из массива на каждом шаге цикла.
Главная сложность — выцепить из сработавшей регулярки конкретный текст, по которому было совпадение. Это нам нужно для того, чтобы заменить найденный фрагмент на фрагмент с тегами вокруг текста. Для этого пойдём на хитрость.
- У нас есть стандартная функция JavaScript под названием replace(). Именно она находит нам текст по шаблону и заменяет на какой-то другой.
- replace() требует двух параметров: что найти и на что заменить. Находить мы будем по регулярным выражениям. А вот с заменой проблема: мы же не знаем, какую именно словоформу нашла наша регулярка. А сказать, на что заменить, нужно однозначно.
- Чтобы обойти это ограничение, мы снова вызовем эту же функцию
replace()
, но со встроенным параметромmatch
. Если перевести на русский, то получится так:
Функция | Что найти | На что заменить | |
replace( | new RegExp(regular, "gi") | function replace(match { | ); |
замени( | То, что ты найдёшь по нашей регулярке, которую ты получила на вход. 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>
Что дальше
Дальше будем развивать мысль: сделаем так, чтобы этим было удобно пользоваться на любой странице, а также дополним боевой список слов.