Сбор органической и рекламной выдачи Яндекса и Google и частотностей Wordstat через XMLRiver — альтернатива Yandex Cloud (Search API и Wordstat v2), когда облака нет или нужен второй путь. Платно: потолок стоимости, журнал, сырые ответы с SHA-256, повтор без повторной оплаты.
Installs into .claude/skills of the current project.
Are you the author of Xmlriver Serp Research?
Add the live security badge to your README. It updates with every re-scan.
[](https://www.skillsdirectory.com/skills/hashgraph-online-xmlriver-serp-research)
---
name: xmlriver-serp-research
description: "Сбор органической и рекламной выдачи Яндекса и Google и частотностей Wordstat через XMLRiver — альтернатива Yandex Cloud (Search API и Wordstat v2), когда облака нет или нужен второй путь. Платно: потолок стоимости, журнал, сырые ответы с SHA-256, повтор без повторной оплаты."
---
# XMLRiver: выдача поиска и Wordstat
Навык собирает исходные данные. Он не выбирает ключи, не оценивает коммерческий смысл, не меняет кампании и не заменяет рекламный кабинет. Порядок работы с Директом задаёт [единый навык](../yandex-direct-unified/SKILL.md); методы официального Wordstat описаны в [справочнике Wordstat](../yandex-wordstat/SKILL.md).
## Когда использовать
XMLRiver — равноправная альтернатива Yandex Cloud, а не его замена. Выбирайте:
- **Yandex Cloud** (Search API, Wordstat v2) — если у вас есть ключ и каталог облака: это официальные интерфейсы Яндекса;
- **XMLRiver** — если облака нет, квоты официального Wordstat (10 запросов в секунду, 100 в час) не хватает на объём задачи или нужна выдача Google.
XMLRiver — сторонний платный сервис. Он разбирает живую выдачу и интерфейс Wordstat, это не официальный API Яндекса и не Google. Условия использования у вас свои; решение о платном расходе принимает пользователь.
Сборщики модуля выбирают путь сами: `--provider yandex-cloud`, `--provider xmlriver` или `auto` (по умолчанию). В режиме `auto` путь выбирается по переменным окружения: берётся тот, для которого задан доступ (облако — `YANDEX_SEARCH_API_KEY`, `YANDEX_SEARCH_IAM_TOKEN` или `YANDEX_WORDSTAT_API_KEY`, XMLRiver — `XMLRIVER_USER` и `XMLRIVER_KEY`). Если заданы оба, не задан ни один или передан файл доступа (`--credentials-file`, `--config`), скрипт остановится и попросит указать `--provider` явно: молча переключаться между платными путями нельзя.
## Что нужно заранее
1. Свой аккаунт XMLRiver с положительным балансом. В личном кабинете, раздел «Настройки сбора», задайте параметры сбора: без этого ссылка сбора может быть недоступна. Если в кабинете включён доступ по IP, добавьте свой адрес, иначе будет ошибка 45.
2. Доступ в переменных окружения процесса: `XMLRIVER_USER` и `XMLRIVER_KEY` (допустим старый синоним `XMLRIVER_USER_ID`) либо закрытый файл с правами `0600` через `--credentials-file`. Ключ не передавать аргументом, не печатать, не сохранять в журналах, отчётах, таблицах и выгрузках.
3. Папка запуска вне репозитория. В ней появятся журнал, сырые ответы и таблицы.
Для первого знакомства в наборе есть общий демо-доступ: флаг `--use-demo-key`. Его баланс общий для всех пользователей и ограничен, скрипт ставит с ним потолок 2 руб. за запуск. Для работы заведите свой аккаунт: демо может закончиться в любой момент.
## До платных запросов
1. Выполните `info`: баланс, цена за 1000 запросов, число потоков, доступность систем. Не считайте старые цены и лимиты действующими.
2. Подготовьте задания: запрос × регион × система × страница. Выдача Яндекса — регион Яндекса (`region_id`, справочник «Регионы для загрузки фидов» в документации Яндекса); Google — страна, при необходимости местоположение и код языка из справочников XMLRiver (`geo.csv`, `countries.xlsx`, `langs.xlsx`, `domains.xlsx`).
3. Выполните `plan` (без сети): число заданий, оценка стоимости, SHA-256 плана. Новый крупный платный пакет покажите пользователю, если разрешение на расход не дано.
4. Не добавляйте платные опции (`--ai`) без необходимости: надбавку `get_info` не показывает. Для `collect --ai` обязательно `--ai-price-per-1000` — надбавка по вашему тарифу, она входит в оценку и потолок; с демо-доступом `--ai` запрещён.
## Сбор
Команды выполняются из каталога навыка (рядом с этим файлом лежит `scripts/xmlriver_collect.py`).
python3 scripts/xmlriver_collect.py info
python3 scripts/xmlriver_collect.py plan --kind serp --jobs-file jobs.tsv --output-dir RUN --engine yandex --ads on
python3 scripts/xmlriver_collect.py collect --kind serp --jobs-file jobs.tsv --output-dir RUN --engine yandex --ads on \
--approve-plan-sha256 <SHA из plan> --max-cost-rub <потолок> --probe 3
python3 scripts/xmlriver_collect.py export --kind serp --jobs-file jobs.tsv --output-dir RUN --engine yandex --ads on
Файл заданий выдачи — TSV в формате `serp-job-template.tsv` единого порядка: `job_id`, `search_query`, `region_id`, необязательные `page`, `engine`, `device`, `enabled`, `layer`, `purpose`, `search_region`, `notes`, `google_country`, `google_lang`, `google_loc`, `google_domain`. Один и тот же файл подходит и сборщику Yandex Cloud: лишние колонки не мешают.
- Перед сетевым вызовом задание записывается в журнал. Каждый ответ сохраняется отдельным файлом с SHA-256 и квитанцией; значения доступа в сохранённом ответе заменяются на `[REDACTED]`.
- Повторный запуск того же плана не отправляет успешные задания снова. Код 15 («результатов нет») — состояние `empty`, не ошибка и не повторяется.
- Временные ошибки `101`, `110`, `111`, `500` повторяются отдельным запуском `--retry-errors` (по умолчанию только эти коды; `--only-codes` сужает список). Прежние попытки сохраняются.
- Задание с неизвестным исходом (`inflight`: обрыв, таймаут) автоматически не отправляется повторно — запрос мог быть оплачен. Посмотрите команду `inflight`; снять задание можно только с `--acknowledge-possible-charge`.
- `31`, `42`, `45` (доступ), `115` (слишком много параллельных запросов, блокировка на 10 минут), `200` (нет денег) и HTTP 429 останавливают пакет. Параллельность держите ниже лимита потоков из `info`. Два `collect` в одном каталоге одновременно запустить нельзя: второй останавливается до сети, а каждое задание захватывается атомарно, поэтому один запрос не оплачивается дважды. `new_requests` в итоге — число фактически отправленных запросов.
## Особенности систем
- **Яндекс**: страницы с нуля, `groupby=10`, регион числом, `domain=ru`, `lang=ru`. Позиция считается только среди результатов `contenttype=organic`. Для второй и следующих страниц абсолютная позиция (`abs_rank_state=verified`) ставится лишь при непрерывной цепочке успешных страниц от нулевой, 10 органических результатов на каждой предыдущей, без пересечений адресов и без смены исправленного запроса. Иначе позиция «не доказана»: номер страницы × 10 ранг не доказывает.
- **Google**: страницы с единицы (скрипт принимает номер с нуля и сам прибавляет единицу), страна и язык из справочников. Местоположение `loc` для крупных городов бывало источником устойчивой ошибки 500 — проверьте пробой, при ошибке работайте на уровне страны.
- Одинаково названные параметры различаются: `lr` у Яндекса — регион числом, у Google — язык кодом; `domain` у Яндекса — строка, у Google — числовой идентификатор.
## Реклама
- Яндекс: `--ads on` добавляет рекламные блоки (`y_topads`, `y_bottomads`; правый блок — `--yandex-right-ads`).
- Google: документация XMLRiver обещает рекламные блоки, но в проверках автора набора (сентябрь–октябрь 2026, в том числе проба 23.10.2026) Google рекламу не возвращал. Перед пакетом сделайте одиночную пробу на заведомо коммерческом запросе; пустой результат не доказывает отсутствие рекламы конкурентов.
- Число объявлений в снимке — не охват рынка. Ноль объявлений в ответе не означает, что рекламы нет в другом месте и в другой момент. Пустые поля сначала проверьте на разборе, потом делайте выводы.
- Сохраняются исходные поля объявления: `url` (отображаемый адрес), `adsurl` (рекламный переход Google), заголовок, текст, быстрые ссылки. Конечная страница не подменяется догадкой: `landing-unresolved`, пока она не подтверждена отдельной проверкой. По рекламным ссылкам скрипт не переходит.
- Заголовок или текст может содержать процентно кодированные теги выделения (`%3Cb%3E`). В сырых полях они сохраняются; для чтения есть отдельные колонки `title_clean` и `snippet_clean`.
## Wordstat через XMLRiver
python3 scripts/xmlriver_collect.py plan --kind wordstat --masks-file masks.tsv --output-dir RUN --regions 225 --pagetypes words,history
python3 scripts/xmlriver_collect.py collect --kind wordstat --masks-file masks.tsv --output-dir RUN --regions 225 --pagetypes words,history \
--approve-plan-sha256 <SHA> --max-cost-rub <потолок>
python3 scripts/xmlriver_collect.py export --kind wordstat --masks-file masks.tsv --output-dir RUN --regions 225 --pagetypes words,history
- Лимита «100 запросов в час» нет; лимит — число потоков аккаунта и ошибки `110`/`115`. Лимиты официального API на XMLRiver не переносятся, и наоборот.
- Каждая маска стоит два платных запроса: `words` (популярные и похожие запросы) и `history` (динамика и общее число). В пробе 23.10.2026 страница `words` вернула до 759 строк на маску.
- Схема ответа другая: `popular` и `associations` (числа строками, в тексте операторы `+`). Общее число по маске даёт только `history` (`totalValue`, за предыдущий месяц). `export` пишет в `RUN/raw_bundle/` файлы `top_requests_*.json` и `dynamics_*.json` и `_manifest.json` в формате облачного сборщика; отчёты волны, спроса и сезонности находят файлы через манифест. При нескольких регионах у каждого свой каталог `raw_bundle/region_<номер>/`, чтобы отчёт волны не смешивал регионы. Повторный `export` пересобирает каталог целиком. Строка с неверной частотностью не теряется молча: файл помечается `partial` в манифесте, строка уходит в `wordstat_row_errors.tsv`, а команда завершается кодом 2. Даты динамики — по московскому времени. Ответ без ожидаемых полей (`popular` или `graph`) считается ошибкой, а не успехом. Если `history` не собирали, `totalCount` в файле отсутствует, а не равен нулю.
- Нет аналога дерева регионов и распределения по регионам: регион передаётся одним числом, для нескольких регионов создаются отдельные задания.
- Числа XMLRiver и официального Wordstat не складывать и не сравнивать без пометки источника: это разные продукты (`provider` в каждом файле).
- Интервалы динамики: `month` — не менее 3 полных месяцев, `week` — не менее 3 недель с понедельника по воскресенье, `day` — не менее 3 дней, конечный день не сегодня. Скрипт проверяет это до запроса; по умолчанию берёт 6 последних завершённых месяцев.
## Разбор и выводы
- Органика (`serp_results.tsv`, колонки как у сборщика Yandex Cloud), колдунщики (`feature_rows.tsv`) и реклама (`ad_rows.tsv`) выгружаются отдельно. Если в плане обе системы, таблицы пишутся по одной на систему (`serp_results_yandex.tsv`, `serp_results_google.tsv` и т. д.): прежние отчёты группируют только по запросу и региону и смешали бы Яндекс с Google. Регион в таблице — фактически использованный (для Яндекса по умолчанию 225). В каждой строке: исходный запрос и задание, регион, система, устройство, время ответа, положение, путь к сырому файлу и его SHA-256.
- Различайте «блока нет в ответе», «поля нет», «ответ с ошибкой» и «задание не выполнено». Статистику покрытия считайте по успешным заданиям и показывайте пропуски, ошибки, период и географию.
- Выводы вида «конкурентов в рекламе нет» по разовому снимку запрещены.
- Смысловая обработка частотностей и ключей — дальше по [единому навыку](../yandex-direct-unified/SKILL.md); здесь автоматический отбор не выполняется.
## Проверка перед сдачей
1. Повторный `collect` по тому же плану даёт ноль новых запросов.
2. `export` строит таблицы только из сохранённых ответов, без сети; контрольные суммы совпадают.
3. Число заданий по состояниям (`success`, `empty`, `error`, `inflight`, `pending`) сходится с планом; расход и баланс до и после записаны (разница общего баланса может включать чужие запросы на том же аккаунте).
4. В отчёте нет ключей, полных адресов запросов и клиентских данных.
5. Расход на XMLRiver указан отдельно от расходов Yandex Cloud ([контроль расходов облака](../yandex-cloud-search-cost-control/SKILL.md) относится только к Yandex Cloud).