Разбор
ИИ-агент анализирует конкурентов в Яндексе: кто в топе, почему они там и что с этим делать
7 из 15 ключей вышли в ТОП-5 за 2 месяца после внедрения рекомендаций ИИ-агента. Python + Яндекс Search API + Claude анализируют ТОП-10 конкурентов за 20 минут вместо 2–3 дней ручной работы.
2–3 дня на анализ конкурентов в выдаче — и делается это раз в квартал, если вообще делается. За три месяца конкуренты успевают переписать страницы, добавить новые разделы и уйти в ТОП, пока ты смотришь на позиции и гадаешь почему они не растут.
Почему ручной анализ не работает как система
Вот как обычно устроен процесс. Раз в квартал (в лучшем случае) SEO-специалист или маркетолог открывает Яндекс, вбивает один из целевых запросов, заходит на каждый из ТОП-10 сайтов, смотрит на структуру страницы, копирует title и H1 в таблицу. По одному запросу это 30–45 минут. По пятнадцати — два-три дня.
При этом сам процесс субъективный. Один человек обратит внимание на структуру заголовков, другой — на длину текста, третий — на LSI-слова. Систематического сравнения не получается. А рекомендации — «добавить ключевое слово в title» — слишком общие, чтобы от них был толк.
Три вещи, которые мешают делать это часто и хорошо:
Время. Два дня работы ради выводов, которые устаревают раньше чем успеваешь их внедрить — плохая сделка. Поисковая выдача меняется быстро, особенно в коммерческих нишах.
Структура. Таблица с конкурентами, куда вручную вбиты title и H1 — это данные, а не инсайты. Из сырых данных нужно ещё извлечь паттерны: что общего у ТОП-3, чего нет у тебя, что можно добавить. На это уходит ещё день.
Частота. Когда процесс занимает три дня, его делают раз в квартал. Когда это 20 минут — каждую неделю. Разница в подходе к SEO принципиальная.
Что анализирует агент
Агент собирает по каждому конкуренту из ТОП-10 шесть типов данных:
| Элемент | Что именно берём | Зачем |
|---|---|---|
| Title | Полный текст, длина в символах | Паттерны заголовков в ТОП |
| H1 | Текст первого заголовка | Как формулирует тему лидер |
| Description | Мета-описание | Конкурентные триггеры в сниппете |
| Структура текста | Все H2 и H3, их количество | Глубина охвата темы |
| LSI-слова | Топ-30 n-грамм из текста страницы | Семантическое окружение |
| Ссылки в тексте | Внутренние ссылки из контента | Перелинковка и тематические кластеры |
Дальше начинается сравнение. Claude получает эти шесть блоков по каждому из ТОП-10 плюс те же данные с твоей страницы — и сравнивает их структурно. На выходе конкретная рекомендация: какой раздел добавить, как переписать H1, каких тематических блоков не хватает для выхода в ТОП.
Схема работы агента
Python — оркестратор. Сам он ни с чем не взаимодействует напрямую, только забирает данные и передаёт дальше. Яндекс Search API отдаёт URL-ы из выдачи по запросу, BeautifulSoup разбирает HTML каждого сайта, Claude получает структурированный JSON и формирует рекомендации.
Важный момент с архитектурой: я не делал Claude «агентом с инструментами», который сам решает что парсить. Для регулярного мониторинга это лишняя сложность. Фиксированная схема сбора данных → одна передача в Claude → отчёт. Так дешевле и предсказуемее.
Код
import httpx
import anthropic
import json
import re
from collections import Counter
from bs4 import BeautifulSoup
YANDEX_SEARCH_API_KEY = "YOUR_API_KEY" # Yandex Cloud IAM-токен
YANDEX_FOLDER_ID = "YOUR_FOLDER_ID" # Folder ID в Yandex Cloud
CLAUDE_API_KEY = "YOUR_CLAUDE_KEY" # Anthropic API key
SEARCH_API_URL = "https://searchapi.api.cloud.yandex.net/v2/web/search"
HEADERS_HTML = {
"User-Agent": "Mozilla/5.0 (compatible; SEO-Analyzer/1.0)",
"Accept": "text/html,application/xhtml+xml",
"Accept-Language": "ru-RU,ru;q=0.9",
}
def get_top10_urls(query: str) -> list[str]:
"""Получаем ТОП-10 URL из Яндекса по запросу."""
payload = {
"query": {"searchType": "SEARCH_TYPE_RU", "queryText": query},
"sortSpec": {"sortType": "SORT_TYPE_BY_RELEVANCE"},
"groupSpec": {"groupMode": "GROUP_MODE_FLAT", "groupsOnPage": 10},
"folderId": YANDEX_FOLDER_ID,
}
headers = {
"Authorization": f"Api-Key {YANDEX_SEARCH_API_KEY}",
"Content-Type": "application/json",
}
with httpx.Client(timeout=30) as client:
r = client.post(SEARCH_API_URL, json=payload, headers=headers)
r.raise_for_status()
data = r.json()
urls = []
for group in data.get("response", {}).get("grouping", []):
for doc in group.get("group", []):
for d in doc.get("document", []):
url = d.get("url", "")
if url and url not in urls:
urls.append(url)
return urls[:10]
def extract_ngrams(text: str, n: int = 2) -> list[str]:
"""Топ-30 биграмм из текста."""
words = re.findall(r'[а-яёa-z]{3,}', text.lower())
ngrams = [' '.join(words[i:i+n]) for i in range(len(words)-n+1)]
counter = Counter(ngrams)
return [ng for ng, _ in counter.most_common(30)]
def parse_page(url: str) -> dict:
"""Парсим страницу: title, h1, description, h2/h3, LSI, ссылки."""
try:
with httpx.Client(timeout=15, follow_redirects=True, headers=HEADERS_HTML) as client:
r = client.get(url)
r.raise_for_status()
soup = BeautifulSoup(r.text, 'lxml')
title = soup.title.get_text(strip=True) if soup.title else ''
h1_tag = soup.find('h1')
h1 = h1_tag.get_text(strip=True) if h1_tag else ''
meta_desc = ''
meta = soup.find('meta', attrs={'name': 'description'})
if meta:
meta_desc = meta.get('content', '')
h2s = [t.get_text(strip=True) for t in soup.find_all('h2')]
h3s = [t.get_text(strip=True) for t in soup.find_all('h3')]
# Основной текст без навигации и футера
for tag in soup(['nav', 'footer', 'header', 'script', 'style']):
tag.decompose()
body_text = soup.get_text(' ', strip=True)
lsi = extract_ngrams(body_text)
# Внутренние ссылки из контента
base_domain = url.split('/')[2] if '/' in url else ''
links = []
for a in soup.find_all('a', href=True):
href = a['href']
if base_domain in href or href.startswith('/'):
text = a.get_text(strip=True)
if text and len(text) > 3:
links.append(text)
return {
'url': url,
'title': title[:120],
'h1': h1[:120],
'description': meta_desc[:200],
'h2_list': h2s[:15],
'h3_count': len(h3s),
'lsi_bigrams': lsi[:20],
'internal_links': list(set(links))[:15],
'error': None,
}
except Exception as e:
return {'url': url, 'error': str(e), 'title': '', 'h1': ''}
def analyze_with_claude(query: str, my_page: dict, competitors: list[dict]) -> str:
"""Claude сравнивает твою страницу с конкурентами и даёт рекомендации."""
client = anthropic.Anthropic(api_key=CLAUDE_API_KEY)
# Берём только успешно спарсенных конкурентов
ok_comps = [c for c in competitors if not c.get('error')]
prompt = f"""Ты SEO-аналитик. Запрос: "{query}"
МОЯ СТРАНИЦА:
{json.dumps(my_page, ensure_ascii=False, indent=2)}
КОНКУРЕНТЫ В ТОП-{len(ok_comps)} (отсортированы по позиции):
{json.dumps(ok_comps, ensure_ascii=False, indent=2)}
Задача: выяви конкретные причины, почему конкуренты выше, и дай практические рекомендации.
Структура ответа:
1. ГЛАВНЫЙ РАЗРЫВ (1–2 предложения: в чём принципиальное отличие ТОП-1 от моей страницы)
2. ЧТО ДОБАВИТЬ В TITLE И H1 (конкретные формулировки с примерами)
3. СТРУКТУРА ТЕКСТА (каких разделов не хватает — с названиями H2)
4. LSI-СЛОВА КОТОРЫХ НЕТ У МЕНЯ (список 10–15 слов/фраз из конкурентов)
5. ТРИ ДЕЙСТВИЯ НА ЭТОЙ НЕДЕЛЕ (конкретные, с критерием «что считать выполненным»)
Пиши по-русски, конкретно, без воды."""
message = client.messages.create(
model="claude-sonnet-4-6",
max_tokens=1500,
messages=[{"role": "user", "content": prompt}]
)
return message.content[0].text
def run_analysis(query: str, my_url: str) -> str:
"""Полный цикл: получить конкурентов → спарсить → проанализировать."""
print(f"Запрос: {query}")
top10 = get_top10_urls(query)
# Убираем свой сайт из списка конкурентов
competitors_urls = [u for u in top10 if my_url not in u]
print(f"Найдено конкурентов: {len(competitors_urls)}")
my_page = parse_page(my_url)
print(f"Своя страница: {my_page.get('title', 'н/д')}")
competitors = []
for i, url in enumerate(competitors_urls[:10], 1):
print(f" Парсим {i}/{len(competitors_urls)}: {url[:60]}...")
competitors.append(parse_page(url))
report = analyze_with_claude(query, my_page, competitors)
return report
# Пример запуска для одного ключа
if __name__ == "__main__":
QUERY = "купить ламинат недорого москва"
MY_URL = "https://example.com/catalog/laminat/"
result = run_analysis(QUERY, MY_URL)
print("\n" + "="*60)
print(result)
Несколько вещей, которые в документации не очевидны.
Яндекс Search API на Yandex Cloud предоставляет два метода: /web/search (синхронный, ответ сразу) и /web/searchAsync (асинхронный, возвращает ID операции — нужно поллить /operations/{id}). Скрипт использует синхронный вариант: проще для старта, ответ получаем в том же запросе. Для потоков из 50+ запросов параллельно стоит перейти на async-версию.
robots.txt конкурентов стоит проверять отдельно. BeautifulSoup не нарушает никаких ограничений — парсинг HTML это то, что делает любой браузер. Но часть сайтов блокирует автоматические запросы через User-Agent или rate limit. Скрипт обрабатывает ошибки через try/except — упавшие URL просто пропускаются.
Микрокавычки в f-строках Python внутри MDX могут вызвать проблемы при рендеринге — именно поэтому в промпте использованы одинарные кавычки вместо тройных.
Есть вопрос по теме?
Пришлю шаблон контент-стратегии и примеры кейсов с цифрами
Пример отчёта Claude
Вот реальный фрагмент отчёта по запросу «ламинат 33 класс купить москва» для магазина строительных материалов:
Обратите внимание на структуру: не «добавьте ключевые слова», а конкретные формулировки с примерами того, как это сделали конкуренты. Критерии выполнения — чтобы не гадать «ну мы вроде добавили».
Ограничения Яндекс Search API
Яндекс в 2024 году перенёс XML API на Yandex Cloud. Старый xml.yandex.ru продолжает работать для аккаунтов с историческим доступом, но новые подключения — только через Yandex Cloud Search API.
Модель доступа: платная подписка с лимитами на количество запросов, привязанная к Folder ID в Yandex Cloud. Бесплатного постоянного уровня нет — есть тестовый период. Актуальные тарифы: cloud.yandex.ru/services/search-api.
Для еженедельного мониторинга 15 ключей расход небольшой: один прогон — 15 запросов к Search API, это около 150 запросов в месяц при запуске раз в неделю. На большинстве тарифных планов это укладывается в минимальный пакет.
Одно практическое ограничение, с которым я столкнулся: API возвращает данные только по поиску в России (searchType: SEARCH_TYPE_RU). Региональная выдача (например, ТОП по Казани) требует отдельного параметра геотаргетинга — lr (номер региона в базе Яндекса).
Как проверить состояние своего SEO прямо сейчас
Диагностика: насколько вы знаете своих конкурентов
4 вопроса — поймёте, где пробел
Кейс: 15 ключей, 2 месяца, 7 позиций в ТОП-5
Интернет-магазин строительных материалов, Москва и МО. 15 коммерческих ключей в нише напольных покрытий. До запуска агента позиции стояли на одном месте восемь месяцев — между 15-й и 35-й строкой выдачи, без существенного движения.
Что сработало, а что нет.
Быстрее всего поднялись ключи, где разрыв был в структуре: у конкурентов были FAQ-блоки и сравнительные таблицы, у нас — просто текст. Добавили — позиции подросли за 2–3 недели.
Медленнее — ключи с высокой конкуренцией, где у ТОП-3 ещё и ссылочная масса в разы больше. Контентные правки помогли, но не дотянули до первой страницы.
Четыре ключа так и остались на 12–18 позиции. Агент честно написал в отчёте: «Контентный разрыв минимален, разница в ссылочном профиле — основной фактор».
Это, кстати, честный ответ. Агент не обещает ТОП по любому запросу — он показывает конкретно где разрыв и что можно сделать.
Как настроить еженедельный мониторинг
Создать аккаунт на cloud.yandex.ru, создать каталог (Folder), подключить сервис Search API. Получить API-ключ или IAM-токен. Проверить актуальный тариф на странице услуги.
cloud.yandex.ru → Каталог → Search API → ВключитьЧетыре библиотеки: anthropic для Claude API, httpx для асинхронных HTTP-запросов, beautifulsoup4 и lxml для парсинга HTML. Python 3.10+.
pip install anthropic httpx beautifulsoup4 lxmlСделать JSON-файл: список пар {query: "запрос", my_url: "https://..."} для каждого целевого ключа. Начинать с 5–10 ключей — меньше расход API и проще проверить качество отчётов.
Прогнать скрипт по 2–3 ключам, посмотреть на рекомендации. Если Claude пишет слишком общо — значит парсинг вернул пустые страницы (часто из-за JavaScript-рендеринга). В таком случае нужен Playwright или Splash вместо httpx.
python competitor_analysis.pyCron каждый понедельник в 9:00 — скрипт прогоняет все ключи из списка, сохраняет отчёты в папку с датой. Можно добавить отправку в Telegram или на email через тот же скрипт.
0 9 * * 1 python /path/to/competitor_analysis.pyГде агент не поможет
Честно о границах — потому что ожидания управляют результатом.
Агент хорошо видит структурные и семантические разрывы: чего не хватает в тексте, как переписать title, каких разделов нет. Это большой класс задач, и он закрывается хорошо.
Агент не видит ссылочный профиль. Если ТОП-1 держится на 500 качественных ссылках, а у тебя 20 — контентные правки поднимут позиции, но не до первого места. Агент иногда пишет об этом явно, но не всегда.
Агент не работает с JavaScript-рендеренными страницами. Если конкурент использует SPA на React или Vue, BeautifulSoup увидит пустую болванку вместо контента. Для таких случаев нужен headless-браузер (Playwright, Puppeteer) — это отдельная тема.
Агент не анализирует поведенческие факторы. Почему ТОП-1 держится несмотря на слабый контент — может быть высокий CTR в сниппете, долгое время на сайте, прямые заходы. Это не видно из HTML.
Но вот что я заметил после нескольких месяцев использования: большинство SEO-задач решаются именно на уровне контента и структуры. Ссылочная конкуренция — в коммерции и в узких нишах. В большинстве тематик разрыв между твоей страницей и ТОП-3 — это три H2, которых ты не написал, и пятнадцать слов, которых нет в тексте.
Есть вопрос по теме?
Пришлю шаблон контент-стратегии и примеры кейсов с цифрами
Источники
AI-агенты · Персональная карта
4 часа потратил — не работает?
Покажу где ты пошёл не туда и как сделать правильно за 2 недели
Получить разбор бесплатно →AI-агенты · 10 мест
Ты работаешь до полуночи — AI-агент будет работать вместо тебя
Покажу какой агент закроет твою главную операционную боль
Узнать свой маршрут →Есть вопрос по теме?
Пришлю шаблон контент-стратегии и примеры кейсов с цифрами
Источники
Читайте также
Часто задаваемые вопросы
- Что такое Яндекс Search API и зачем он нужен для анализа конкурентов?
- Яндекс Search API (бывший Яндекс XML) — программный интерфейс для получения результатов поиска Яндекса без браузера. Скрипт делает запрос с ключевой фразой и получает ТОП-10 URL в XML. Дальше каждый URL можно автоматически обойти и разобрать: заголовки, мета-теги, структуру текста, LSI-слова. Это заменяет ручной просмотр выдачи и копирование данных в таблицу.
- Сколько времени экономит ИИ-агент по сравнению с ручным анализом конкурентов?
- Ручной анализ ТОП-10 по одному запросу — 30–45 минут: зайти на каждый сайт, переписать H1, title, description, посмотреть структуру текста, найти LSI-слова. По 15 ключам это 2–3 рабочих дня. Агент делает то же самое за 20–30 минут, включая формирование отчёта Claude с конкретными рекомендациями.
- Какие ограничения есть у Яндекс Search API?
- Яндекс Search API (Yandex Cloud) работает по подписке, лимиты на запросы устанавливаются на уровне аккаунта в Yandex Cloud. Бесплатного постоянного доступа нет — есть тестовый период. Для еженедельного мониторинга 15–30 ключей расход небольшой: обычно укладывается в несколько сотен запросов в месяц. Проверить актуальные тарифы: cloud.yandex.ru/services/search-api.
- Что именно Claude анализирует в сниппетах конкурентов?
- Claude получает структурированный JSON: H1, title, description, первый абзац текста, количество заголовков H2/H3, список ссылок со страницы, частотные n-граммы из текста. Модель сравнивает это с твоей страницей и выдаёт конкретные рекомендации: каких слов не хватает, какую структуру добавить, где конкурент явно лучше и почему.
- Нужно ли уметь программировать, чтобы запустить агента?
- Достаточно базового Python: установить библиотеки, вставить API-ключи, запустить скрипт. Всё остальное делает код из статьи. Для автоматического еженедельного запуска понадобится cron (Linux) или любой планировщик задач. Более сложная часть — зарегистрироваться в Yandex Cloud и пройти верификацию для доступа к Search API.
- Какой реальный результат дало внедрение рекомендаций агента?
- Кейс из статьи: интернет-магазин строительных материалов, 15 коммерческих ключей. После двух итераций доработки страниц по рекомендациям ИИ-агента — 7 ключей вышли в ТОП-5, ещё 4 в ТОП-10. Срок — 2 месяца с момента первого запуска агента. До этого позиции стояли на месте 8 месяцев.
Канал «Лёха Маркетолог»
Практика без воды: кейсы, инсайты, разборы. 1–2 поста в неделю.
Пока без комментариев. Будьте первым.