Позиции сайта в поиске живут собственной жизнью: сегодня страница держится в топе по одному слову, завтра уезжает на второй экран, а конкуренты тем временем тестируют новые заголовки сниппетов. Команда, которая проверяет выдачу руками, видит отдельные снимки вместо непрерывной картины. Когда в работе сотни слов, десяток городов и регулярный отчёт для руководства, ручной сбор превращается в узкое место: человек устаёт быстрее, чем растёт список запросов, а свежесть наблюдений теряется уже к середине дня.
Ниже разобран рабочий путь получения поисковой выдачи из Python: чем сервис-посредник SerpAPI отличается от самописного парсера, что именно он возвращает, где проходит граница допустимого в правилах поисковиков и на чём экономят бюджет без потери качества аналитики.
Задачи аналитики, для которых нужен сбор поисковой выдачи в структурированном виде
Специалисты по поисковому продвижению работают с выдачей как с материалом для измерений, а не как с картинкой на экране. Базовая задача остаётся прежней: мониторинг позиций по основному списку слов. Динамика по каждому запросу показывает, какие страницы растут, какие проседают и где вмешательство даст быстрый эффект.
Второй пласт: анализ конкурентов. Интересует, кто занимает верх выдачи, как сформулированы их заголовки, какие страницы подведены под отдельные потребности и как часто соперники меняют подходы. Третий пласт: рекламные блоки. По каким словам показывается реклама, кто из рекламодателей встречается чаще всех и какие форматы он задействует, вопросы, без которых реклама остаётся лотереей.
Отдельного внимания заслуживают информационные элементы: похожие вопросы, локальный блок, блоки товаров, видео и быстрые ответы. Их состав меняется от слова к слову и от города к городу, и часто именно такой блок, а не классическая десятка ссылок, отбирает заметную часть кликов.
Для всех перечисленных задач нужен не снимок экрана, а структура: позиция, заголовок, сниппет, ссылка, пометка о типе блока. Домен при необходимости вычисляется из ссылки. Только структура позволяет считать средние позиции, доли доменов в топе, вхождение по регионам и строить ряды наблюдений на недели вперёд. Из-за этого требования самописный парсер сырой страницы оказывается лишь половиной дела: вторая половина уходит на разбор HTML селекторами, и он ломается при каждой смене вёрстки.
Регулярные наблюдения превращаются в инструмент проверки гипотез. Команда выпустила новый раздел или переписала заголовки, и через пару недель ряды позиций показывают, сработала ли идея. Обвал после технического релиза почти всегда означает проблему с индексацией, а не каприз наблюдателя, и это знание экономит недели споров о причинах.
Прямой автоматический съём выдачи и его конфликт с правилами поисковиков
У поисковых систем есть условия использования, и в них прямо сказано: автоматический массовый доступ к выдаче без отдельного разрешения не предусмотрен. В технической литературе такой свод правил сокращают до латинской аббревиатуры TOS. Ограничение выглядит логичным: поисковик защищает инфраструктуру от перегрузки и держит под контролем качество ответа, которое видит живой пользователь.
На практике конфликт проявляется быстро. Счётчик подозрительных запросов с одного адреса растёт, система показывает проверку на человечность, затем временно закрывает доступ или отдаёт урезанный ответ. Обход ограничений превращается в бесконечную гонку с обновлениями защиты и съедает инженерное время, которое можно было потратить на саму аналитику. Честно говоря, именно на этом этапе у большинства команд самописные парсеры и заканчиваются.
Есть запасная колея: официальные интерфейсы самих поисковых систем. Они существуют, но у них жёсткие дневные лимиты, урезанный состав ответа и заметные ограничения по регионам. Рекламных блоков и части информационных элементов там часто нет вовсе, а для массовых серийных проверок лимита не хватает. Образуется зазор между тем, что официально разрешено и удобно, и тем, что нужно аналитику по полноте картины.
Именно этот зазор закрывают сервисы-посредники, и SerpAPI относится к известным представителям класса.
SerpAPI как посредник между скриптом на Python и поисковой системой
Схема работы прозрачна. Клиентский скрипт отправляет запрос с параметрами, сервис через собственную инфраструктуру получает страницу выдачи, разбирает её и возвращает готовый JSON. Внутри ответа лежат типизированные блоки: обычные результаты с позициями, реклама сверху и снизу страницы, похожие вопросы, локальный блок, панели со справкой и прочие элементы выдачи. Для каждого обычного результата приходят позиция, заголовок, сниппет и ссылка, поэтому селекторы писать не нужно.
Техническая нагрузка переходит на сторону сервиса: он поддерживает пул адресов для съёма, следит за сменой вёрстки, обновляет собственные парсеры и при необходимости читает страницу в полноценном браузерном окружении. Формальная часть тоже смещается к сервису: отношения оформлены договором и тарифами, а не самодельной схемой, за которую в одиночку отвечал бы один разработчик.
Оплата идёт за запрос. Есть бесплатный пробный объём и платные тарифы, которые отличаются количеством обращений и скоростью обслуживания. Конкретные суммы зависят от действующего плана, поэтому цифры в статье не приводятся, важнее сама механика: каждый запрос стоит денег, и архитектура сбора обязана быть экономной.
Есть и приятное свойство посредника: один интерфейс обслуживает несколько поисковых систем. Параметр engine переключает движок, а структура ответа остаётся предсказуемой, поэтому сравнение выдачи разных поисковиков собирается в одну таблицу почти без дополнительного кода.
Набор движков не ограничен обычным веб-поиском: через тот же интерфейс доступны карты, новости, изображения и товарная выдача. Для локального бизнеса мониторинг карт даёт не меньше пищи, чем классические позиции: точки на карте, отзывы и рейтинги складываются в отдельную ветку наблюдений. Новостная выдача показывает, чьи материалы собирают видимость по информационным поводам, и это полезно при планировании публикаций.
Клиентская библиотека SerpAPI для Python и первый рабочий скрипт
Для Python у сервиса есть официальная клиентская библиотека. Установка занимает одну команду:
pip install google-search-results
Минимальный скрипт выглядит так:
from serpapi import GoogleSearch
search = GoogleSearch({
"engine": "google",
"q": "зерновая кофемашина",
"hl": "ru",
"gl": "ru",
"num": 10,
"api_key": "секретный_ключ"
})
data = search.get_dict()
for item in data.get("organic_results", []):
print(item["position"], item["title"], item["link"])
Метод get_dict возвращает ответ словарём, get_json отдаёт сырую строку, get_html пригодится, когда нужен исходный код страницы. Если ключ неверный или лимит исчерпан, в ответе появится поле "error" с описанием причины, поэтому проверку ошибок удобно встроить в код сразу, а не выяснять причину пустых таблиц спустя неделю.
Скорость упирается в тариф: у каждого плана своя граница запросов в минуту, и при серийных проверках между обращениями разумно ставить паузу. Без паузы часть вызовов будет отброшена, и прогоны придётся повторять, то есть платить дважды за одно и то же.
Параметры географии, языка и пагинация при масштабных проверках
Выдача зависит от точки наблюдения. Параметр location задаёт город или регион, причём точное написание локации берут из справочника сервиса, потому что параметр ждёт каноничное имя. Пара gl и hl отвечает за страну и язык интерфейса, device переключает компьютер и мобильное устройство. Для локального бизнеса разброс между городами бывает драматичным: по одному и тому же слову в одном городе страница видна в топе, в другом её нет даже на второй странице.
Пагинация идёт через параметр start. Нулевое значение даёт первую страницу, каждый следующий шаг сдвигает окно выдачи глубже, а число результатов на страницу задаётся параметром num. При массовом сборе глубокие страницы нужны редко: статистика позиций почти всегда живёт на первой странице, а стоимость растёт с каждой.
Для чистоты рядов наблюдений параметры фиксируют. Один и тот же список слов запускают с одними и теми же значениями географии, языка и устройства, иначе разница в позициях будет отражать смену условий съёма, а не реальное продвижение. Дата проверки, слово, регион и устройство записываются рядом с результатами, чтобы любой ряд можно было восстановить и объяснить.
Обработка ответов, таблицы и хранение результатов на стороне Python
Ответ сервиса приходит в JSON, поэтому дальше идёт привычная работа с данными в Python: разбор словарей, сборка таблиц, агрегации и графики. Типовой путь выглядит так: из каждого ответа выбираются обычные и рекламные блоки, строки складываются в таблицу pandas, затем считаются агрегаты по доменам и словам. Домен вычисляется из ссылки средствами стандартной библиотеки, и это надёжнее, чем полагаться на состав полей конкретного движка.
import pandas as pd
from urllib.parse import urlparse
from serpapi import GoogleSearch
def fetch_serp(kw):
search = GoogleSearch({
"engine": "google",
"q": kw,
"hl": "ru",
"gl": "ru",
"api_key": "секретный_ключ"
})
return search.get_dict()
rows = []
for kw in ["кофемашина", "зерновой кофе"]:
data = fetch_serp(kw)
for item in data.get("organic_results", []):
link = item.get("link", "")
rows.append({
"keyword": kw,
"position": item.get("position"),
"domain": urlparse(link).netloc,
"title": item.get("title")
})
df = pd.DataFrame(rows)
summary = df.groupby("domain")["position"].mean().sort_values()
print(summary)
df.to_csv("results.csv", index=False)
Для хранения сырых ответов подходит встроенная база SQLite, для подросших проектов PostgreSQL. Сырой JSON стоит сохранять полностью: требования к отчётам меняются в самый неподходящий момент, и переразбор накопленных ответов бесплатен, в отличие от повторных обращений к сервису.
Автоматизацию собирают на планировщике: скрипт по расписанию берёт список слов, проверяет кэш, выполняет недостающие запросы, пишет таблицу и отправляет уведомление при сбоях. Поле "error" служит маркером для повторного прогона, а журнал запусков помогает понять, где именно сбор начал спотыкаться.
Расходы на больших объёмах и дисциплина запросов с кэшированием
Арифметика объёма безжалостна: число обращений растёт как произведение списка слов на список регионов и устройств. Триста слов и пять городов дают полторы тысячи проверок за один прогон, а за месяц ежедневных прогонов накопится около сорока пяти тысяч обращений. Любая лишняя частота или глубина умножает счёт так же спокойно, как и полезная часть проекта.
Кэш закрывает заметную долю бюджета. Ключ кэша строится из слова, региона, языка, устройства и даты, одинаковые сочетания в пределах отчётного окна повторно не запрашиваются. Если отчёт выходит раз в неделю, ежедневный сбор второстепенных слов избыточен, и список делится на частоты: ядро проверяется каждый день, средний пласт раз в неделю, остальное раз в месяц.
Свод правил экономного сбора выглядит так:
- проверять кэш перед каждым новым обращением и хранить сырые ответы за весь отчётный период;
- делить список слов на частоты проверок и не гонять весь массив ежедневно;
- вычищать дубликаты и пустые слова до запуска, а не после получения счёта;
- фиксировать географию, язык и устройство, чтобы исключить повторы из-за рассинхронизации настроек;
- запускать объёмные выгрузки с тестовой выборки и оценивать расход до полного масштаба.
Отдельная строка расходов связана с глубиной: вторая и третья страницы выдачи нужны редко, а стоят столько же, сколько первая. Отказ от лишней глубины и от экзотических комбинаций регионов часто сокращает бюджет заметнее любых технических ухищрений.
SerpAPI закрывает техническую часть задачи и снимает с команды груз поддержки самодельного парсера, а Python берёт на себя обработку, таблицы и хранение. Граница риска проходит по условиям использования поисковиков, и её стоит уважать: умеренные объёмы, кэширование и дисциплина запросов удерживают проект в разумных пределах и по деньгам, и по отношениям с источником выдачи.