Google, это входная дверь к большей части публичной информации в интернете, а страница, которую он возвращает по запросу, нечто большее, чем список синих ссылок. Одна страница результатов поиска может содержать органические объявления, платные объявления, блок «Похожие вопросы», информационную панель, локальный пакет с картой и строку похожих поисковых запросов, каждый из которых является отдельным блоком структурированных данных. Для тех, кто занимается исследованием ключевых слов, отслеживанием позиций, анализом конкурентов или маркетинговой разведкой, эта страница является одним из богатейших публичных наборов данных в интернете.
Это руководство представляет собой широкий обзор того, как парсить страницы поиска Google: что на самом деле представляет собой SERP, почему обычный HTTP-запрос блокируется, реалистичные методы сбора данных и работоспособный пример, который парсит блоки функций и обрабатывает пагинацию. Если вам нужно краткое пошаговое руководство с кодом на Python, наш специализированный учебник по парсингу результатов Google с Python является дополняющим материалом. Всё здесь ограничено публичными данными SERP, которые любой может видеть без учётной записи, а раздел о правовых вопросах ближе к концу, не просто формальность, поэтому прочитайте его, прежде чем направить что-либо на реальные объёмы данных.
Что вы создадите
К концу у вас будет небольшой Python-скрипт, который отправляет публичный URL поиска Google в API с поддержкой SERP, получает разобранный JSON и считывает каждый блок функций в чистые записи. В качестве рабочего примера мы используем запрос "data science" и извлекаем следующие поля из ответа:
- Результаты поиска. Органические объявления, каждое с заголовком, URL назначения, отображаемым фрагментом и позицией на странице.
- Реклама. Спонсорские объявления, показанные выше или ниже органических результатов, когда запрос носит коммерческий характер.
- Похожие вопросы. Раскрывающийся блок похожих вопросов, каждая запись с вопросом, кратким ответом и ссылкой на источник.
- Похожие поисковые запросы. Строка предлагаемых дополнительных запросов, которую Google показывает внизу страницы.
- Локальный пакет. Блок с картой ближайших мест, когда запрос имеет локальный характер.
- Количество результатов. Сообщаемое общее число результатов, которое управляет пагинацией.
Анатомия страницы результатов поиска Google
Чтобы хорошо парсить SERP, сначала нужна мысленная модель его сборки. Google не возвращает единый однородный список; он компонует страницу из нескольких отдельных блоков, и то, какие блоки появляются, зависит от намерения запроса. Один и тот же парсер должен распознавать каждый из них. Вот части, которые имеют значение.
- Органические результаты. Основной список ранжированных веб-страниц. Каждый содержит заголовок, URL назначения, фрагмент и иногда дату или сайтлинки. Это блок, который больше всего важен для SEO, поскольку позиция здесь и означает «ранжирование».
- Реклама. Платные объявления с пометкой «Спонсировано», показанные вверху и внизу страницы для коммерческих запросов. Они похожи на органические результаты, но куплены, поэтому конкурентная разведка рассматривает их как отдельный поток.
- Похожие вопросы (PAA). Раскрывающийся список похожих вопросов. Каждый открывается с кратким ответом из страницы-источника и ссылкой на эту страницу. PAA, это полезная карта вопросов, которые пользователи задают по теме.
- Информационная панель. Информационный блок справа (люди, компании, места, объекты), созданный из Knowledge Graph Google. В нём отображаются ключевые факты, изображения и связанные объекты без необходимости переходить по ссылке.
- Локальный пакет. Карта плюс краткий список ближайших предприятий, показываемый когда запрос имеет локальный характер ("кофейни рядом"). Он содержит названия, рейтинги и адреса и отличается от полных результатов Google Maps.
- Похожие поисковые запросы. Строка предлагаемых запросов внизу страницы, полезная для расширения ключевых слов.
-
Пагинация. Элементы управления для перехода глубже в результаты, работающие через смещение
startв URL, а не через номер страницы.
Практический вывод: «парсить Google», это на самом деле парсинг нескольких независимых блоков, которые оказываются на одной странице. Хороший экстрактор возвращает каждый из них как отдельный список, чтобы вы могли использовать их независимо в дальнейшем. Для более детального изучения блока с вопросами см. статью как парсить «Похожие вопросы» Google.
Почему обычный запрос не работает на Google
Если отправить обычный HTTP-запрос к https://www.google.com/search?q=... из скрипта, вы почти никогда не получите страницу, которую видите в браузере. Google, одна из наиболее агрессивно защищённых целей в интернете, и этому способствуют две причины, которые взаимно усиливают друг друга.
Во-первых, страница динамическая. Большая часть современного SERP, особенно блоки функций, формируется с помощью JavaScript после загрузки исходного HTML. Обычный requests.get видит оболочку, а не отрисованный результат, поэтому нужные вам данные просто отсутствуют в полученных байтах. Во-вторых, Google внимательно следит за автоматизацией. Запрос без реальных заголовков браузера, с IP дата-центра или приходящий быстрее, чем человек мог бы напечатать, получает страницу согласия, CAPTCHA или прямую блокировку. Продолжительный скрапинг с одного адреса быстро приводит к ограничению скорости для этого адреса.
Поэтому рабочий скрапер Google требует двух вещей в одном запросе: IP-адреса, который платформа воспринимает как обычного посетителя, и там, где страница опирается на скрипты, браузера, который её отрисовывает. Можно собрать это самостоятельно с помощью безголового браузера плюс пула ротирующихся резидентных прокси, но поддержание этого парка в рабочем состоянии, это большая часть всей работы и большая часть затрат. Альтернатива, управляемый API с поддержкой SERP, который объединяет отрисовку, ротацию IP и обработку CAPTCHA в одном вызове и возвращает готовые данные. Мы рассмотрим компромисс между этими подходами далее.
Методы парсинга Google: управляемый API или самостоятельное решение
Есть два честных способа сделать это в реальном масштабе, и стоит ясно смотреть на оба.
Самостоятельный стек. Вы запускаете безголовый браузер (Playwright или Selenium) для отрисовки страницы, маршрутизируете его через пул ротирующихся резидентных прокси, чтобы ни один IP не выгорел, добавляете управление заголовками и отпечатками, чтобы трафик выглядел человеческим, и создаёте логику повтора и решения CAPTCHA для запросов, которые всё равно получают вызов. Это работает, и для разового академического проекта это может быть правильным решением. Загвоздка, в обслуживании: прокси истекают, отпечатки устаревают, Google выпускает изменения вёрстки, а вашему решателю CAPTCHA нужна постоянная работа. Скрапер, это лёгкая часть; поддержание его разблокированности, это работа. Наши руководства по парсингу без блокировок и обходу CAPTCHA подробно описывают этот стек.
Управляемый API. Вы отправляете URL на эндпоинт, который уже владеет пулом резидентных IP, слоем отрисовки и обработкой CAPTCHA, и он возвращает либо готовый HTML, либо, что лучше, SERP, разобранный в JSON. Вы полностью пропускаете инфраструктуру и платите за успешный запрос. Компромисс в том, что вы зависите от провайдера и его парсера. Для большинства производственных задач отслеживания позиций и исследований это прагматичный выбор, поскольку время, которое вы потратили бы на управление прокси-парком, стоит дороже, чем плата за запрос. В примере ниже используется Crawling API Crawlbase со встроенным парсером Google SERP.
Остальная часть руководства использует путь с управляемым API, поскольку он позволяет показать реальный разобранный вывод без 200 строк прокси-кода. Концепции парсинга (какой блок что собой представляет, как поля отображаются) переносятся на самостоятельный стек без изменений, если вы выберете этот путь.
Предварительные требования
Перед написанием кода нужно подготовить несколько вещей. Ни одна из них не займёт много времени.
Базовые знания Python. Вы должны уверенно писать и запускать Python-скрипты и устанавливать пакеты через pip. Если хотите освежить знания по парсингу для самостоятельного подхода, наше руководство по использованию BeautifulSoup в Python охватывает основы.
Python 3.8 или новее. Проверьте версию командой python --version. Если Python не установлен, скачайте его с python.org или через дистрибутив вроде Anaconda.
Аккаунт Crawlbase и токен. Зарегистрируйтесь, откройте панель управления и скопируйте токен запроса. Вы получаете до 20 000 бесплатных запросов без кредитной карты, и вы платите только за успешные запросы. Храните токен как пароль: он аутентифицирует ваши запросы, поэтому не добавляйте его в систему контроля версий.
Настройка проекта
Создайте виртуальное окружение, чтобы зависимости проекта оставались изолированными, затем установите лёгкую обёртку Crawlbase для Python, которая отправляет запросы к API и считывает ответы.
python --version python -m venv serp_env source serp_env/bin/activate pip install crawlbase
В Windows активируйте окружение командой serp_env\Scripts\activate вместо строки с source. Пакет crawlbase, это небольшая обёртка без зависимостей вокруг API: вы инициализируете его с токеном и вызываете get с URL. SQLite, который мы используем для хранения результатов позднее, поставляется с Python, поэтому устанавливать что-то дополнительно не нужно.
Шаг 1: Получение SERP через Crawling API
Страницы поиска Google работают через Normal-токен Crawling API, поскольку парсер читает разметку, отрисованную на сервере. Инициализируйте клиент с токеном, укажите URL поиска и запросите ответ в формате JSON, чтобы получить чистый конверт вместо исходного HTML.
from crawlbase import CrawlingAPI import json # Initialize the Crawling API with your Crawlbase token api = CrawlingAPI({"token": "YOUR_CRAWLBASE_TOKEN"}) # URL of the Google search page you want to scrape google_search_url = "https://www.google.com/search?q=data+science" # Ask the API for a JSON response envelope options = {"format": "json"} response = api.get(google_search_url, options) if response["headers"]["cb_status"] == "200": body = json.loads(response["body"].decode("latin1")) print(json.dumps(body, indent=4, sort_keys=True)) else: print("Failed to retrieve the page. Status:", response["status_code"])
API возвращает JSON-конверт с двумя полями статуса и телом. cb_status (legacy pc_status), статус Crawlbase, а original_status, то, что вернул сам Google; проверка cb_status == "200" означает, что блок или страница-перехватчик всплывают как ошибка, а не передают мусор вниз по цепочке. Тело возвращается в байтах, поэтому его нужно декодировать с latin1 перед json.loads. Запуск этого выводит исходный конверт страницы, что подтверждает работоспособность получения данных до написания кода парсинга.
Проверка cb_status всегда читает 200, потому что запрос достиг Google как обычный посетитель с самого начала. Crawling API получает SERP с ротирующегося резидентного IP, отрисовывает его, когда блок функций требует браузера, и обрабатывает CAPTCHA, которые иначе остановили бы обычный запрос, поэтому вы пропускаете запуск безголового парка и пула резидентных прокси самостоятельно. Начните с публичного URL поиска на бесплатном тарифе.
Шаг 2: Парсинг блоков функций SERP
Читать исходный HTML и писать селекторы для каждого блока функций вручную возможно, но Google часто выпускает изменения вёрстки и обфусцирует имена классов, поэтому написанные вручную селекторы постоянно ломаются. Crawling API поставляется со встроенным скрапером google-serp, который делает этот парсинг за вас и возвращает каждый блок в виде чистого списка. Вы включаете его одной опцией.
from crawlbase import CrawlingAPI import json api = CrawlingAPI({"token": "YOUR_CRAWLBASE_TOKEN"}) google_search_url = "https://www.google.com/search?q=data+science" # The google-serp scraper parses the page into structured JSON options = {"scraper": "google-serp"} response = api.get(google_search_url, options) if response["headers"]["cb_status"] == "200": parsed = json.loads(response["body"].decode("latin1")) serp = parsed["body"] # Each feature block comes back as its own key organic = serp.get("searchResults", []) ads = serp.get("ads", []) paa = serp.get("peopleAlsoAsk", []) related = serp.get("relatedSearches", []) local = serp.get("snackPack", {}) total = serp.get("numberOfResults", 0) print(f"Organic results: {len(organic)}") print(f"Ads: {len(ads)}") print(f"People Also Ask: {len(paa)}") print(f"Related searches: {len(related)}") print(f"Total results reported: {total}") else: print("Failed to retrieve the page. Status:", response["status_code"])
Скрапер google-serp возвращает объект body, ключи которого напрямую соответствуют блокам функций из раздела анатомии. searchResults, это органический список, ads, спонсорские объявления, peopleAlsoAsk, блок с вопросами, relatedSearches, строка предложений, а snackPack, локальный пакет со ссылкой на карту и результатами мест. numberOfResults, это сообщаемый итог, который вы будете использовать для управления пагинацией. Каждая запись в searchResults содержит title, url, description и position, поэтому записи готовы к использованию без какой-либо работы с селекторами.
Коммерческий запрос показывает рекламу; информационный заполняет блок «Похожие вопросы»; локальный запрос заполняет локальный пакет. Всегда считывайте каждый ключ через .get(key, default), чтобы отсутствующий блок возвращал пустой список, а не вызывал KeyError. Один и тот же запрос также может возвращать разные блоки в разные дни, когда Google настраивает свою вёрстку.
Шаг 3: Сборка полного скрипта
Теперь свяжите получение и парсинг в один работоспособный скрипт, который переводит органические результаты и блок с вопросами в плоские записи и записывает их в JSON. Это форма, которую вы расширите для реальной задачи.
from crawlbase import CrawlingAPI import json api = CrawlingAPI({"token": "YOUR_CRAWLBASE_TOKEN"}) options = {"scraper": "google-serp"} def fetch_serp(url): response = api.get(url, options) if response["headers"]["cb_status"] != "200": raise Exception(f"Unable to crawl '{url}'") parsed = json.loads(response["body"].decode("latin1")) return parsed["body"] def extract(serp): results = [] for item in serp.get("searchResults", []): results.append({ "position": item.get("position"), "title": item.get("title"), "url": item.get("url"), "description": item.get("description"), }) questions = [q.get("title") for q in serp.get("peopleAlsoAsk", [])] related = [r.get("title") for r in serp.get("relatedSearches", [])] return { "searchResults": results, "peopleAlsoAsk": questions, "relatedSearches": related, "numberOfResults": serp.get("numberOfResults", 0), } def main(): url = "https://www.google.com/search?q=data+science" serp = fetch_serp(url) data = extract(serp) with open("google_results.json", "w", encoding="utf-8") as f: json.dump(data, f, ensure_ascii=False, indent=2) print(f"Saved {len(data['searchResults'])} organic results") if __name__ == "__main__": main()
Запустите командой python main.py. Функция fetch_serp получает разобранный SERP и вызывает исключение при любом не-200, чтобы ошибки были заметны, а extract сводит нужные вам блоки в один объект. Замените запрос в URL, и те же две функции обработают всё, что вернётся. Чтобы проследить каждый вопрос «Похожих вопросов» к полному ответу и источнику, поля description и destination для каждой записи уже есть в ответе, поэтому вы можете расширить extract без дополнительного запроса.
Как выглядит вывод
Скрапер google-serp возвращает структурированный объект с ключами для каждого блока функций. Вот сокращённый пример того, что возвращается для запроса "data science", чтобы вы знали имена полей перед написанием кода.
{ "numberOfResults": 2520000000, "ads": [], "peopleAlsoAsk": [ { "position": 1, "title": "What exactly does a data scientist do?", "description": "A data scientist uses data to understand and explain the phenomena around them...", "destination": { "text": "Coursera", "url": "https://www.coursera.org/articles/what-is-a-data-scientist" } } ], "relatedSearches": [ { "title": "data science jobs", "url": "https://google.com/search?q=Data+science+jobs" } ], "searchResults": [ { "position": 1, "title": "What is Data Science?", "url": "https://www.ibm.com/topics/data-science", "description": "Data science combines math and statistics, specialized programming..." } ], "snackPack": { "mapLink": "", "results": [] } }
Каждый блок, это отдельный ключ, поэтому вы можете брать только органические searchResults для отслеживания позиций, только peopleAlsoAsk для исследования контента или только ads для конкурентного анализа. Поскольку блоки рекламы и локальный блок пусты для информационного запроса вроде этого, ваш код всегда должен считывать каждый ключ по умолчанию, а не предполагать его наличие.
Пагинация по результатам
Одна страница, это демонстрация; реальная работа с SERP требует более глубокого погружения. Google пагинирует с помощью параметра запроса start, смещения в списке результатов, а не номера страницы. Примерно с девятью или десятью органическими результатами на страницу, start=10 даёт вторую страницу, start=20, третью, и так далее. Поле numberOfResults из парсера, ваша верхняя граница, хотя на практике Google редко возвращает более нескольких сотен результатов для одного запроса.
import time base = "https://www.google.com/search?q=data+science" all_results = [] for page in range(3): start = page * 10 url = f"{base}&start={start}" serp = fetch_serp(url) all_results.extend(extract(serp)["searchResults"]) time.sleep(2) # pace the crawl print(f"Collected {len(all_results)} results across 3 pages")
Сформируйте URL каждой страницы со смещением, получите его через API и спарсите той же функцией. Единственная привычка, которая поддерживает длительный запуск в рабочем состоянии, это дозирование: короткий sleep между запросами распределяет трафик вместо того, чтобы отправлять его в плотном цикле. Для сохранения собранного запишите заголовок, URL, описание и позицию каждой записи в базу данных; SQLite, самый простой вариант, поскольку он поставляется с Python и не требует сервера. Оттуда вы также можете сохранить те же строки в CSV для таблицы или загрузить их в любой инструмент анализа, который вы используете.
Масштабирование и поддержание разблокированного состояния
Переход от нескольких запросов к тысячам меняет задачу с «спарсить страницу» на «оставаться разблокированным со временем». Несколько привычек делают длительную задачу устойчивой.
- Дозируйте и варьируйте. Распределяйте запросы и ротируйте их по многим запросам, а не листайте один запрос на полной скорости. Взрывной, повторяющийся трафик, самый быстрый способ получить вызов.
- Опирайтесь на ротацию. Пул резидентных IP распределяет запросы по множеству адресов реальных пользователей, чтобы ни один не превысил лимит. Crawling API делает это за вас; если вы создаёте собственный стек, наше руководство по ротации прокси для парсинга результатов Google охватывает это подробно.
- Повторяйте неудачные попытки бесплатно. Crawlbase не взимает плату за неудачные запросы, поэтому заблокированный или недоступный URL можно повторить без затрат. Создайте небольшую логику повтора с откатом, вместо того чтобы терять страницы.
- Следите за дрейфом вёрстки. Google часто выпускает изменения SERP. Управляемый парсер поглощает большинство из них за вас, но если поле начинает возвращаться пустым, вёрстка, вероятно, переместилась, поэтому проверьте форму ответа, прежде чем предполагать, что ваш код неправильный.
Если вы предпочитаете маршрутизировать собственный трафик через ротирующийся пул, а не использовать управляемый API, Smart AI Proxy предоставляет ту же ротацию резидентных IP в виде прокси-эндпоинта. Для задач, требующих распараллеливания на множество запросов одновременно, асинхронный краулер позволяет ставить URL в очередь и собирать результаты по мере завершения, а не ждать каждого запроса последовательно. Для конкретной проблемы страниц согласия и верификации наш материал по обходу CAPTCHA при парсинге Google рассматривает это более подробно.
Законен ли парсинг результатов поиска Google?
Допустимость парсинга Google зависит от условий использования Google, вашей юрисдикции и того, как вы используете данные. Парсинг публичных страниц результатов поиска, заголовков, ссылок, фрагментов и позиций, которые любой может видеть без входа в аккаунт, это вид публичных данных, который суды в нескольких юрисдикциях рассматривали как собираемые. Тем не менее условия использования Google ограничивают автоматический доступ к его сервисам, поэтому парсинг может противоречить этим условиям вне зависимости от тщательности вашего инструментария. Ни один из приведённых здесь кодов не меняет этого; он лишь решает техническую часть задачи. Прочитайте условия Google и его robots.txt и рассматривайте оба документа как границу того, что вы собираете и как быстро.
Несколько правил, которых стоит придерживаться. Собирайте только публичные данные SERP и держитесь подальше от всего, что за логином, от личных данных людей и от защищённых авторским правом медиа, которые вы будете распространять с сайтов по ссылкам. Поддерживайте достаточно скромный объём запросов, чтобы не нагружать инфраструктуру Google, и дозируйте сканирование, а не запускайте его на полную мощность. Цель, структурированные публичные данные для исследований, SEO и анализа рынка, а не массовая переиздание индекса Google.
Там, где существует официальный API, предпочтите его. Google предлагает санкционированные продукты для конкретных нужд: Custom Search JSON API для программного поиска в определённой области и Search Console для данных о производительности вашего собственного сайта. Они дают структурированный доступ в рамках чётких условий. Они не охватывают каждый вариант использования скрапера SERP, именно поэтому парсинг публичных данных сохраняется, но когда ваш проект вписывается в официальный эндпоинт, он является более чистым путём. Если вы взвешиваете более широкие компромиссы, наш материал о сложностях парсинга результатов поиска Google стоит прочитать.
Ключевые выводы
- SERP состоит из множества блоков, а не одного списка. Органические результаты, реклама, «Похожие вопросы», информационная панель и локальный пакет, это независимые блоки; парсите каждый отдельно.
- Обычные запросы блокируются. Google отрисовывает блоки функций с JavaScript и бросает вызов трафику из дата-центров, поэтому нужна отрисованная страница с доверенного резидентного IP.
- Управляемый API или самостоятельное решение. API с поддержкой SERP объединяет отрисовку, ротацию и обработку CAPTCHA в одном вызове; самостоятельный стек работает, но обслуживание является реальной стоимостью.
-
Пагинация через смещение start. Увеличивайте
startшагами по десять для более глубокого погружения, используйтеnumberOfResultsкак границу и дозируйте запросы с паузой. - Оставайтесь в рамках публичных данных. Соблюдайте условия использования Google и robots.txt, избегайте логинов и личных данных, поддерживайте скромный объём и предпочтите официальный API там, где он подходит.
Часто задаваемые вопросы
Из чего состоит Google SERP?
Страница результатов поиска состоит из нескольких отдельных блоков: органических результатов (ранжированные веб-объявления), рекламы (платные объявления для коммерческих запросов), «Похожих вопросов» (раскрывающийся блок с вопросами), информационной панели (блок объектов из Knowledge Graph Google), локального пакета (карта плюс ближайшие предприятия) и похожих поисковых запросов. Какие блоки появляются, зависит от намерения запроса, поэтому хороший скрапер считывает каждый блок независимо и терпимо относится к отсутствующим.
Почему обычный запрос не работает на Google?
Две причины складываются. Большая часть современного SERP, особенно блоки функций, отрисовывается с JavaScript, поэтому необработанный HTTP-запрос видит оболочку, а не готовую страницу. Google также внимательно следит за автоматизацией и бросает вызов трафику с IP дата-центров или запросам без реальных заголовков браузера с помощью страницы согласия или CAPTCHA. Получение данных через API с поддержкой SERP, использующий ротирующиеся резидентные IP и отрисовку, делает запрос похожим на запрос обычного посетителя.
Использовать управляемый API или создать собственный скрапер?
Для разового проекта самостоятельный стек (безголовый браузер плюс ротирующиеся прокси) может подойти. Для производственного отслеживания позиций или масштабных исследований управляемый API обычно является прагматичным выбором, потому что основная работа, это поддержание скрапера разблокированным, а не его написание: прокси истекают, отпечатки устаревают, и Google выпускает изменения вёрстки. Концепции парсинга переносятся между двумя подходами, поэтому выбор в основном о том, кто обслуживает инфраструктуру.
Как конкретно парсить результаты поиска Google с помощью Python?
В примере здесь используется обёртка Crawlbase для Python со скрапером google-serp для получения разобранного JSON без написания селекторов. Для краткого пошагового руководства по Python, которое строит запрос и парсинг шаг за шагом, см. наш специализированный учебник по парсингу результатов поиска Google с Python, который является дополнением к этому широкому материалу.
Как пагинировать через больше результатов Google?
Используйте параметр запроса start, смещение в результатах, а не номер страницы. Примерно с десятью органическими результатами на страницу, start=10, вторая страница, start=20, третья, и так далее. Сформируйте каждый URL со смещением, получите его через API, спарсите той же функцией и делайте паузу пару секунд между запросами, чтобы дозировать сканирование, а не перегружать систему.
Законен ли парсинг результатов поиска Google?
Публичные данные SERP, заголовки, ссылки, фрагменты и позиции, которые любой может видеть без учётной записи, в целом рассматриваются как собираемые, но условия использования Google ограничивают автоматический доступ, поэтому парсинг может вступить в конфликт с этими условиями. Прочитайте условия Google и robots.txt, избегайте логинов и личных данных, поддерживайте скромный объём и предпочтите официальный эндпоинт, например Custom Search JSON API или Search Console, где он подходит для вашего варианта использования.
Обходите любой сайт в масштабе, без борьбы с инфраструктурой.
Crawlbase берёт на себя прокси, отпечатки и CAPTCHA, чтобы ваша команда выпускала конвейеры данных вместо поддержки обвязки краулинга. 1 000 запросов бесплатно, без карты.
