Открыв сайт в браузере, вы узнаёте, что видит браузер. Это другой вопрос, чем что видит краулер, и на современном сайте ответы могут отличаться полностью.
Вот метод, которым пользуемся мы, и — что полезнее — способы, которыми он врёт.
Спрашивайте от имени бота, а не от своего
Вся проверка — это один запрос с нужным User-Agent и подсчёт слов:
check() {
curl -sS -A "$2" --max-time 15 "$1" | python3 -c "
import sys, re
h = sys.stdin.read()
b = re.search(r'<body[^>]*>(.*)</body>', h, re.S)
if not b: print(0); raise SystemExit
t = re.sub(r'<script.*?</script>|<style.*?</style>|<noscript.*?</noscript>', '', b.group(1), flags=re.S)
print(len(re.sub(r'<[^>]+>', ' ', t).split()))"
}
for ua in \
"Mozilla/5.0 (compatible; Googlebot/2.1; +http://www.google.com/bot.html)" \
"Mozilla/5.0 (compatible; bingbot/2.0; +http://www.bing.com/bingbot.htm)" \
"GPTBot/1.0 (+https://openai.com/gptbot)" \
"OAI-SearchBot/1.0" \
"ClaudeBot/1.0" \
"PerplexityBot/1.0" \
"Applebot/0.1"
do
printf "%-24s %s слов\n" "${ua:0:22}" "$(check https://example.com/ "$ua")"
done
Две вещи делают эту проверку стоящей запуска, а не предположения.
Прогоняйте по каждому адресу из sitemap, а не по главной. Сайт может отдавать первую страницу с сервера и оставлять пустой каждую глубокую. Именно они и должны были ранжироваться.
Сравнивайте между агентами. Если Googlebot получает содержимое, а GPTBot —
ноль, где-то у вас есть правило — в robots.txt, в CDN, в антибот-продукте, —
которое решает за вас, каким движкам можно вас читать. Это решение стоит
принимать осознанно, а не наследовать.
Потом прочитайте свои логи
Проверка через curl говорит, что краулер получил бы. Лог доступа говорит,
что произошло на самом деле, и это единственное доказательство во всём этом
упражнении, которое никто не оспорит.
Если запросы логируются с заголовками, сгруппируйте их по user-agent и по дням:
const BOT = /(Googlebot|bingbot|GPTBot|OAI-SearchBot|ChatGPT-User|ClaudeBot|PerplexityBot|Google-Extended|Applebot|YandexBot|Amazonbot|DuckDuckBot)/i;
for (const line of readLines(logFile)) {
const entry = parse(line);
const hit = BOT.exec(entry.headers['user-agent'] ?? '');
if (hit) counts[hit[1]][entry.day]++;
}
Четыре месяца такого рассказали нам больше, чем любой инструмент. Выборка из той недели, когда мы включили пререндер на сайте, который отдавал краулерам пустое тело:
| краулер | до | после |
|---|---|---|
| Googlebot | 1–5 запросов в день | 167, затем 451 |
| GPTBot | 1–3 в день | 208 за один день |
| YandexBot | 0 | 84 |
Двух вещей в этих данных не было видно больше нигде. Четыре краулера, которые не
появлялись никогда — PerplexityBot, Applebot, DuckDuckBot, Amazonbot, — пришли за
неделю. И ChatGPT-User, агент, открывающий страницу, пока человек ждёт ответа в
ChatGPT, перешёл от «никогда» к 33 запросам за день.
Считайте ещё и разные страницы, а не только запросы. Тысяча обращений к главной и тысяча, размазанная по шестидесяти страницам, означают противоположное.
Три способа, которыми эти проверки врут
Это часть, которую стоит забрать с собой. Каждый из них дал ложный вывод в нашем собственном аудите, прежде чем мы это поймали.
curl без User-Agent — это не краулер
Мы сообщили, что sitemap.xml клиента отдаёт 403. Он и отдавал — curl
с агентом по умолчанию. Антибот-защита сайта блокирует неизвестных клиентов, а
curl/8.5.0 — неизвестный клиент.
Тот же файл, запрошенный правильно:
curl 403
Chrome 200
Googlebot 200
bingbot 200
Никакой SEO-проблемы не было вовсе. Дефект был в инструменте. Никогда не
запускайте проверку краулера без -A, а когда результат выглядит тревожно,
перезапустите его как Chrome и как Googlebot, прежде чем верить.
Оператор site:, прочитанный через скрапер, — не доказательство
Мы использовали запросы site:, полученные с поисковика, чтобы заключить, что
три клиентских сайта не проиндексированы. Два были.
Поисковики отдают автоматическим клиентам деградированные страницы. В одном
прогоне страница результатов для site:createli.md была заполнена результатами с
форума поддержки немецкого мобильного оператора. Число результатов тоже было
шумом: site: по домену без единого совпадения вернул «около 2 160 000
результатов».
Что действительно надёжно, по порядку: Search Console — это движок говорит
вам напрямую; поиск с ограничением по домену через настоящий поисковый API; и
обычный запрос по бренду, который хотя бы подтверждает, что что-то
проиндексировано. Число результатов site:, вытащенное из HTML-страницы, не
подтверждает ничего.
Половина «AI-краулеров» в ваших логах — не AI-краулеры
Группировка четырёх месяцев логов по user-agent дала таблицу, в которой
PerplexityBot запрашивал /.env.production, /.env.bak и /.git/HEAD; Applebot
просил /backend/.env; OAI-SearchBot — /credentials.yaml; а YandexBot —
/wp-config.php.bak.
Настоящий Perplexity не сканирует файлы окружения. Это сканеры под именем бота, потому что ботовые user-agent часто освобождены от ограничений по частоте.
Два следствия. Ваша статистика по краулерам завышена, если не проверять — через обратный DNS или по опубликованным диапазонам IP каждого вендора. И каждый из тех путей стоит проверить на своём сайте:
for p in /.env /.env.production /.git/config /credentials.yaml /wp-config.php.bak; do
printf "%-26s %s\n" "$p" "$(curl -sS -o /dev/null -w '%{http_code}' "https://example.com$p")"
done
Всё, кроме 403 или 404, — находка. На одном сайте каждый из них отдавал 200, потому что SPA-фолбэк подставлял главную страницу на любой неизвестный путь, — а это, отдельно, ещё и бесконечное множество soft 404.
Какой вывод делать
Порядок, который выдерживает проверку:
curlпо каждому агенту, по всему sitemap. Говорит, существует ли содержимое для краулера вообще.- Собственный лог доступа, сгруппированный по агенту и дню. Говорит, кто реально приходил и что забрал. Самое сильное доступное доказательство, и оно ваше.
- Search Console. Говорит, что движок решил потом. На этот вопрос больше не отвечает ничего.
И одна дисциплина под всеми тремя: если результат вас удивил, подозревайте инструмент раньше сайта. Дважды за один аудит удивительной находкой оказалось наше собственное измерение.