Google отказывал нашему скрейперу, пока мы не поняли, что он смотрит не на IP

—

от автора

Задача звучала скучно: собирать выдачу Google. Много, регулярно, через обычные резидентные прокси и без платных SERP API.

Первая версия честно открывала Chrome, вбивала запрос и получала капчу. Вторая получала капчу чуть реже. Где-то между двадцатым экспериментом и вкладкой, которая съела 3 гигабайта памяти, стало понятно, что мы всё это время думали о Google неправильно.

В итоге получился открытый инструмент, google-browser-scraper (GitHub, MIT): настоящий Chrome под Patchright, который отдаёт выдачу в JSON. Но эта статья не про код. Она про то, что мы намерили по дороге, и про то, что не сработало. Конкретных рецептов обхода здесь не будет: только что мерили, как мерили и что увидели.

Сначала про то, как мы считали

Всё, что ниже, — это прогоны на сервере с Windows, через резидентные прокси, обычно новый IP на каждый тест. Успех — это когда Google отдал страницу с результатами. Капча, блок, «необычный трафик» — отказ. Отказ мы никогда не записываем как «0 результатов»: в JSON у каждой страницы есть явный вердикт. Звучит очевидно, но иначе о проблеме узнаёшь через неделю по странной статистике.

И одно правило, которое мы выучили больно: сравнивать варианты можно только в одном окне времени, вперемешку. У Google бывают дни, когда не проходит ничего, и дни, когда проходит половина. Если вариант А мерили во вторник, а Б в среду, вы сравнили вторник со средой.

Headless убивает всё, а мы искали причину где угодно, кроме него

Однажды контрольные прогоны перестали работать. Совсем.

Режим браузера

Обслужено запросов

headless

0 из 35

обычное окно

149 из 150

Сначала мы решили, что неудачный час. Потом — что неудачный день. Потом придумали третье объяснение. И только после гигабайта сожжённого трафика сравнили настройки с прогоном, который работал, и нашли --headless, который случайно попал в проверочный скрипт.

Мораль, которую я теперь повторяю себе каждый раз: если что-то сломалось, сначала ищи, чем этот запуск отличается от работающего. Объяснение, которое хорошо звучит, — не то же самое, что причина.

Свежий браузер Google не любит. Браузер с историей — любит

Чистый профиль на чистом IP, который сразу идёт искать, проходит редко. Тот же профиль, который сначала походил по обычным сайтам, проходит в разы чаще:

Пропущено IP

сразу в поиск

11 из 44

сначала обычные сайты

36 из 44

Важно оказалось не только куда ходить, но и как долго оставаться. Короткие визиты помогали заметно хуже, чем визиты, похожие на чтение. Когда мы удлинили их, доля пропущенных свежих IP выросла почти вдвое.

Цена у этого есть: прогрев одного IP стоит десятки мегабайт трафика. Поэтому вся остальная история — о том, как платить за него реже.

Google доверяет не IP, а профилю

Это главный эксперимент. Берём профиль браузера, который Google уже пропустил, и переносим его на другой, новый IP.

Что попало на новый IP

Пропущено

свежий профиль

2 из 16

профиль, который Google уже пропустил

23 из 35

тот же профиль, но без кук Google

0 из 12

Новый IP, ни одного запроса с него раньше — и Google пропускает, если браузер «тот же». Убери куки Google — и доверие пропадает целиком.

Для меня это поменяло картину. IP — это проверка на входе, а репутацию несёт профиль. Отсюда и практическое следствие для любого скрейпера: прогретый профиль ценнее прогретого IP, и терять его на каждой смене прокси — значит каждый раз платить заново.

Один IP держит тысячу запросов, и каждый следующий дешевле

Сначала мы меняли IP каждые 10 запросов, «на всякий случай». Потом каждые 50. Потом решили наконец проверить, где предел.

Предела мы не нашли. За три с лишним тысячи запросов на уже пропущенных IP Google не отказал ни разу. Удержание заканчивалось, когда отваливался сам резидентный IP, а один IP отработал 1210 запросов подряд, и тест остановили мы, а не Google.

Бонус, которого мы не ждали: страница дешевеет по мере удержания, потому что прогревается кэш браузера.

Запросы на одном IP

Трафик внутри страницы

1-50

~0,9 MB

51-100

~0,6 MB

200+

~0,4 MB

Бесконечно дешеветь она, конечно, не может. После ~200-го запроса цена встаёт на плато и стоит там тысячу запросов подряд. Всё общее (скрипты, стили, картинки Google) уже в кэше, а остаётся то, что уникально для каждого запроса: HTML выдачи, превью, фоновые запросы. Это не закэшировать, поэтому около 0,65 MB на запрос — потолок экономии даже для IP, который живёт вечно.

Кэш можно унести с собой

Раз страницу удешевляет кэш, а доверие живёт в профиле, коллега предложил очевидное: переносить на новый IP профиль вместе с кэшем. Проверили в одном окне, вперемешку:

Что перенесли на новый IP

Трафик на поиск, всё включено

профиль без кэша

~1,1 MB

профиль с кэшем

~0,73 MB

Минус треть трафика на старте каждого нового IP. Google это не смутило: в обоих вариантах обслужены все поиски.

Вкладка Google на 3 гигабайта

Когда мы стали держать один IP по 500+ запросов, скрейпер начал падать с MemoryError. Python был ни при чём. Журнал Windows показал, что процесс-рендерер вкладки с Google вырос до 3,2 GB за 548 поисков. А после падения скрейпера этот процесс продолжал висеть и держать память.

Первая идея — открывать новую вкладку раз в N поисков — не сработала вообще: память росла с той же скоростью. Моя гипотеза (не проверенная): Chrome держит вкладки одного сайта в одном процессе, и новая вкладка садится в тот же раздутый процесс. Сработал только перезапуск браузера: память идёт пилой, кэш на диске остаётся, а Google после перезапуска продолжает пускать. С этим контрольный прогон на 1000 запросов в два браузера прошёл без единой ошибки памяти.

А время суток вообще важно?

Я был уверен, что да: у нас даже прогоны стояли на вечер, «потому что вечером Google добрее». По сырым цифрам так и выходило: вечером проходило вдвое больше, чем ночью.

Потом мы сравнили часы внутри одного дня, и разница почти исчезла: лучшее окно (16-19 UTC) выигрывает у среднего за день около трёх пунктов. «Вдвое» давали не часы, а дни: прогоны в плохие дни случайно чаще попадали на ночь. Время суток почти не важно. День важен очень. А прогретый браузер проходит в 84% случаев в любое время.

Что не сработало

Пожалуй, самая полезная часть.

  • Уходить со страницы сразу после чтения. Экономит 35-45% трафика, но Google начал отказывать посреди удержания у 3 IP из 10, а без этого — у 0 из 6. Не стоит того.

  • Прогреть в Chrome, а искать лёгким клиентом. Идея красивая: дорогой браузер только для прогрева, дальше curl_cffi или Obscura с теми же куками. 0 из 50. Google пускал Chrome и не пускал лёгкий клиент с той же «историей».

  • Новая вкладка вместо перезапуска браузера — см. выше.

Сколько это стоит

Контрольный прогон последней версии: 1000 запросов из 1000, около 1 GB резидентного трафика вместе с прогревом, 1 час 40 минут в два браузера на сервере с 4 ядрами. При длинном удержании IP — около 0,8 GB на тысячу. Это заметно дешевле премиальных SERP API, хотя и немного медленнее: около 8-10 секунд на запрос на один браузер против 3-5 секунд у API.

Что я вынес

  1. Google оценивает браузер, а не IP. IP — проверка на входе.

  2. Тот, кого Google уже пустил, может делать сотни запросов. Дорого только начало.

  3. Если результат внезапно поменялся, ищите, что поменялось у вас, прежде чем винить Google.

  4. Сравнивайте варианты только в одном окне времени. Дни у Google слишком разные.

Попробовать

pip install google-browser-scraperpatchright install chromiumgoogle-browser-scraper search "best running shoes" \  --proxy "http://USER-session-{session}:PASS@gate.example.com:7000" \  -o results.jsonl

Нужен любой резидентный прокси со sticky-сессиями. Все замеры в статье сделаны на прокси NodeMaven, с ними сессии настраиваются флагом --nodemaven. Ещё есть Docker-образ, локальный HTTP API в привычном формате SERP API и MCP-сервер, через который AI-агент получает живой поиск Google.

Если у вас на других прокси или другой ОС получается иначе, напишите в issues. Мне правда интересно, где наши выводы не держатся.

ссылка на оригинал статьи https://habr.com/ru/articles/1097926/