April 29, 2025

Разработал свой сервис текстовой аналитики — SEO Doc 2.2

История судьбы

Ежедневно я работаю с поисковыми алгоритмами, в частности заспамленностью и водой. Эти два параметра настраиваются точечно: проверил текст, поправил, проверил еще раз — всплыли артефакты, поправил еще раз. Циклов может быть десятки — в зависимости от того, насколько «вкусным» для браузера должен стать материал.

Большое внимание я уделяю спаму. Я всегда контролирую повторы и академическую тошноту, это одно из важнейших звеньев определения seo-успеха статьи. Text.ru отлично выделяет ключи, но довести лонгрид до идеала — долгий процесс, поэтому вычесывание условного гайда для руководителей B2B может обойтись в сотни и тысячи рублей.

Несколько месяцев назад, работая над статьей объемом 35.000 символов, я потратил около 1000 рублей, пока проверял-поправлял. Тут либо корпоративный тариф, либо часами выглядывать каждый повтор в тексте, чтение которого занимает полчаса.
Около 100 000 символов улетело на проверку статьи, объёмом 10.000 знаков без пробелов. В денежном эквиваленте это около 120 рублей. За одну статью. А за Ашманова заплатить?

День, когда я решил изменить свою жизнь

Не то чтобы я стукнул кулаком по столу, но решил найти новый инструмент для анализа текста. Порыл интернет, что-то было, но не совсем то. Мой запрос был в текстовом редакторе, через который можно быстро найти нужное слово, подсветить, заменить и мгновенно увидеть новую статистику. Отличный метод борьбы со спамом вместо постоянного ожидания завершения анализа, который предлагал text.ru. Некоторые предлагали то, что было нужно мне, но по отдельности.

За несколько лет ежедневного взаимодействия с нейросетями я подучился промпт-инжинирингу. В прошлом году составил инструкцию для Claude на 17 страниц А4, чтобы тот писал human-like content. Вот фрагмент промпта, занимающий примерно 0,01% от общего объёма руководства для ИИ по гуманизации текста. Это функциональная реализация энтропийного анализа:

def token_entropy(text, ngram=1):
    """
    Вычисляет энтропию n-граммной структуры текста.
    Оптимальные значения энтропии для человеческих тексто
    в: 3.8-4.2 бит/символ
    """
    from collections import Counter
    import math
    
    tokens = [text[i:i+ngram] for i in range(len(text)-ngram+1)]
    freq = Counter(tokens)
    total = len(tokens)
    
    entropy = -sum((count/total) * math.log2(c
    ount/total) for count in freq.values())
    return entropy

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

График, сгенерированный Sonar по выданным данным. Статья, для которой делалась иллюстрация: teletype.in/@glavdef/ottok

Реализация

Всё началось с выбора формата, платформы, методов реализации.
Была идея сделать целое приложение, но это технически сложнее, а преимуществ практически нет. Остановился на HTML-коде (на нем обычно пишутся сайты) в связке с JavaScript и CSS.

Попросил Claude 3.7 Sonnet выступить в качестве эксперта в области программирования. Рассказал основные требования и получил первый набросок кода. Это был примитивный сервис, который выглядел как заброшенный сайт 2010-х. Перенес код в Visual Studio Code и следующие 10 дней точечно прорабатывал каждый нюанс: добавлял новые правила, менял алгоритмы, тестировал и удалял некачественные закономерности.

Visual Studio Code — бесплатный редактор кода от Microsoft для различных языков программирования.

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

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

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

const CASE_ENDINGS_MAP = {
// Женский род, 1-е склонение
'а': ['а', 'ы', 'е', 'у', 'ой', 'ою', 'ами', 'ах'],
'я': ['я', 'и', 'е', 'ю', 'ей', 'ею', 'ями', 'ях'],
// Мужской/средний род, 2-е склонение
'': ['', 'а', 'у', 'ом', 'е', 'ы', 'ов', 'ам', 'ами', 'ах'],
'о': ['о', 'а', 'у', 'ом', 'е', 'а', '', 'ам', 'ами', 'ах'],
'е': ['е', 'я', 'ю', 'ем', 'и', 'ей', 'ям', 'ями', 'ях'],
// 3-е склонение
'ь': ['ь', 'и', 'и', 'ь', 'ью', 'и', 'ей', 'ям', 'ями', 'ях'],
// Специальные случаи
'ие': ['ие', 'ия', 'ию', 'ием', 'ии', 'ий', 'иям', 'иями', 'иях'],
'ия': ['ия', 'ии', 'ию', 'ией', 'ии', 'ий', 'иям', 'иями', 'иях']
];

Создал отдельное пространство для предлогов, союзов и частиц — всему, что формирует заспамленность текста.

Просто список служебных слов, которые выводятся в отдельную панель

const serviceWords = [
// Предлоги
"в", "на", "с", "к", "у", "по", "от", "из", "без", "для", "до", "за", "над", "под", "при", "через", "о", "об", "про", "перед",
"со", "ко", "во", "обо", "надо", "передо", "между", "вокруг", "около", "возле", "мимо", "вдоль", "против", "вне", "внутри", "кроме",
"сквозь", "среди", "вслед", "вопреки", "благодаря", "согласно", "навстречу",
// Союзы
"и", "а", "но", "или", "да", "если", "что", "чтобы", "как", "когда", "хотя", "потому", "ибо", "будто", "пока", "ли", "либо", "также", "тоже", "зато",
"ни", "то", "же", "поскольку", "словно", "точно", "едва", "лишь", "коли", "иначе", "нежели", "чем", "однако", "итак", "значит",
// Частицы
"не", "ни", "же", "бы", "ведь", "вот", "только", "лишь", "даже", "уже", "еще", "то", "ну", "таки", "именно", "просто", "прямо", "разве",
"неужели", "ли", "вон", "вроде", "якобы", "дескать", "мол", "де", "авось", "навряд", "пусть", "хоть"
];

Результат

Весь код вышел на 2700 строк. HTML — фундамент; вычислительные алгоритмы (логика) строятся на архитектуре JavaScript; анимации, реакция — CSS. В целом здесь всё просто: каждое слово, введенное в поле ввода, проверяется по корню, окончанию и другим правилам. Схожие слова группируются в одну ячейку и выводятся в соответствующий блок.

Для наглядности я добавил раздел «ТОП 10», в который входит 10 самых часто встречаемых в тексте слов, и «заспамленность», куда отправляются все предлоги, союзы и частицы.

Когда всё было готово, увлекся и добавил светлую версию, потому что иногда работаю напротив окна. Инструмент имеет баги и неточности, всё-таки это не моя специализация. Хотя для первого опыта недурно. Решил назвать «SEO Doc», типа лечит текст от мусора, помогает в SEO-оптимизации. «2.2» — одно из обновлений UI.

Скриншот интерфейса SEO Doc 2.2

Попробовать

Исходный код разместил на GitHub. Чтобы запустить:

  1. Скачайте файл на устройство (Кнопка «Download ZIP»).
  2. Запустите HTML через браузер.
  3. Пользуйтесь.

❗️ Сервис не кеширует ваш прогресс, сохраняйте текст где-нибудь в другом месте, чтобы не терять изменения.

Если вы подсветили слово, изменили текст, а потом подсветили другое — прогресс сбросится. Чтобы такого не было, снимайте выделение слова, нажимая на кнопку «Сбросить» (она правее акцентной кнопки «Рассчитать»).

Кнопка скачивания справа, сверху