Google Shopping, одна из наиболее плотных e-commerce-площадок в интернете. На одной странице результатов собраны названия товаров, цены, продавцы, рейтинги и ссылки от десятков ритейлеров, а именно такая структура данных нужна для мониторинга цен или маркетинговых исследований. Если вы что-то продаёте онлайн, публичные листинги покажут, сколько берут конкуренты и кто прямо сейчас предлагает тот или иной товар.

В этом руководстве показано, как парсить данные Google Shopping с помощью Python надёжным способом. Вы создадите небольшой рабочий скрапер, который получает отрисованную страницу результатов Shopping через Crawling API, разбирает каждый листинг с помощью BeautifulSoup, обрабатывает пагинацию и экспортирует записи в JSON и CSV для отслеживания цен. Весь учебник ограничен публичными листингами Shopping, которые видны без аккаунта, а раздел о законности в конце не является шаблонным текстом, поэтому прочитайте его перед тем, как направить скрапер на реальные объёмы.

Что вы создадите

Скрипт на Python, который принимает публичный URL-адрес поиска Google Shopping, получает HTML через Crawling API и извлекает структурированную запись для каждого товара на странице. В качестве примера мы используем запрос "louis vuitton bags" и будем извлекать следующие поля из каждого листинга:

  • Название, название товара в листинге.
  • Цена, отображаемый текст цены, ключевой сигнал для мониторинга цен.
  • Продавец, магазин или ритейлер, предлагающий товар.
  • Рейтинг, средняя оценка покупателей, если она указана.
  • Ссылка, URL страницы товара в Google Shopping.

Почему обычный запрос не работает в Google Shopping

Если отправить простой HTTP-запрос к URL Google Shopping из скрипта, вы редко получите ту чистую страницу, которую видите в собственном браузере. Здесь есть два препятствия. Во-первых, Google отрисовывает большую часть сетки Shopping с помощью JavaScript и адаптирует ответ в зависимости от запрашивающего IP и региона, поэтому зарубежный адрес дата-центра может вернуть стену согласия, другую валюту или неполный контент. Во-вторых, Google отслеживает автоматизированный трафик: запросы, не похожие на реальный браузер, получают в ответ CAPTCHA или блокировку ещё до получения листингов.

Таким образом, рабочий скрапер Google Shopping должен сочетать в одном запросе два свойства: IP-адрес, который платформа воспринимает как реального посетителя, и браузер, отрисовывающий страницу при использовании скриптов. Это можно собрать самостоятельно с помощью headless-браузера и пула ротирующих резидентских прокси, но поддержание их в рабочем состоянии и составляет основную часть работы. Crawling API объединяет всё это в одном вызове: вы передаёте ему URL, он получает страницу с доверенного резидентского IP, отрисовывает её при необходимости и возвращает готовый HTML для парсинга.

Почему здесь важны регион и ротация

Google Shopping показывает разные товары, валюты и продавцов в зависимости от того, откуда поступает запрос. Запрос с резидентского IP в нужной стране выглядит как обычный покупатель, тогда как зарубежный адрес дата-центра сразу вызывает подозрение. Crawling API ротирует резидентские адреса на стороне сервера и позволяет фиксировать страну, поэтому вы получаете листинги, которые увидел бы местный покупатель. Можно начать с до 20 000 бесплатных запросов без карты.

Предварительные требования

Перед написанием кода нужно подготовить несколько вещей. Это займёт немного времени.

Базовый Python. Вы должны уметь писать и запускать скрипты на Python и устанавливать пакеты через pip. Если BeautifulSoup вам не знаком, наше руководство по использованию BeautifulSoup в Python охватывает основы парсинга, на которые опирается этот учебник.

Python 3.8 или новее. Проверьте версию командой python --version. Если Python не установлен, скачайте его с python.org или через дистрибутив вроде Anaconda.

Аккаунт Crawlbase и токен. Зарегистрируйтесь, откройте панель управления и скопируйте токен запроса. Crawlbase выдаёт два типа токенов: обычный для статических страниц и JavaScript-токен для страниц с браузерной отрисовкой. Google Shopping в большинстве регионов работает с обычным токеном. Вы получаете до 20 000 бесплатных запросов: 1 000 при регистрации и больше по мере прохождения шагов онбординга. Храните токен как пароль: он аутентифицирует ваши запросы, поэтому не добавляйте его в систему контроля версий.

Настройка проекта

Создайте виртуальное окружение, чтобы зависимости проекта оставались изолированными, затем установите две библиотеки, необходимые скраперу.

bash
python --version

python -m venv shopping_env
source shopping_env/bin/activate

pip install crawlbase beautifulsoup4

В Windows активируйте окружение с помощью shopping_env\Scripts\activate вместо строки с source. Две зависимости выполняют основную работу: crawlbase, официальный клиент, который отправляет запрос к Crawling API и возвращает отрисованный HTML; beautifulsoup4 разбирает этот HTML, позволяя извлекать каждое поле по CSS-селектору.

Шаг 1: получение страницы через Crawling API

Начнём с получения HTML. Инициализируйте клиент CrawlingAPI с вашим токеном, затем напишите небольшую функцию scrape_google_shopping(), которая отправляет целевой URL с набором параметров, проверяет, что страница вернула статус 200, и возвращает разобранный HTML. Параметры фиксируют страну, задают реалистичный user agent и дают странице несколько секунд на отрисовку перед получением HTML.

python
from crawlbase import CrawlingAPI
from bs4 import BeautifulSoup
import json

# Initialize CrawlingAPI with your access token
crawling_api = CrawlingAPI({"token": "YOUR_CRAWLBASE_TOKEN"})

# Request options: pin the region, look like a real browser, let the page render
options = {
    "country": "US",
    "user_agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/123.0.0.0 Safari/537.36",
    "page_wait": 5000,
}

def fetch_html(url):
    response = crawling_api.get(url, options)
    if response["headers"]["cb_status"] != "200":
        print(f"Failed to fetch the page. Status: {response['headers']['cb_status']}")
        return None
    return response["body"].decode("utf-8")

if __name__ == "__main__":
    url = "https://www.google.com/search?q=louis+vuitton+bags&tbm=shop&num=20"
    html = fetch_html(url)
    if html:
        print(html[:500])

Клиент возвращает ответ, в котором headers["cb_status"], это статус, который Crawlbase зафиксировал при получении страницы. Проверка на него означает, что блокировка или стена согласия выведет чёткое сообщение вместо того, чтобы передать мусор в парсер. URL поиска содержит три важных элемента: q, запрос, tbm=shop переключает Google в режим Shopping, а num=20 запрашивает двадцать результатов на страницу. Запустите скрипт командой python shopping.py, и в первых 500 символах вы должны увидеть реальную разметку Shopping, это подтвердит, что получение работает, прежде чем вы напишете хоть один селектор.

Crawlbase Crawling API

Проверка cb_status (legacy pc_status) всегда возвращает 200, потому что запрос изначально поступает к Google как от настоящего покупателя. Crawling API получает страницу с ротирующего резидентского IP в зафиксированной стране, отрисовывает JavaScript-сетку Shopping и отдаёт готовый HTML, избавляя вас от необходимости запускать парк headless-браузеров и закупать пул резидентских прокси. Начните с публичного URL Shopping на бесплатном тарифе.

Структура страницы результатов Google Shopping

Прежде чем писать селекторы, полезно понять структуру страницы результатов. Откройте поиск Shopping в браузере, кликните правой кнопкой на товар и выберите «Просмотр кода», чтобы увидеть структуру в инструментах разработчика. Каждый результат состоит из нескольких элементов.

  • Листинги товаров. Каждая карточка содержит название, изображение, цену, имя продавца или ритейлера и рейтинг, если он есть. Это основной объём данных для парсинга.
  • Пагинация. Результаты распределяются по нескольким страницам, переход к которым осуществляется изменением смещения start в URL.
  • Фильтры и сортировка. Фильтры по диапазону цен, бренду и категории меняют то, что возвращает страница, что важно при необходимости получить конкретный срез данных.
  • Рекламные листинги. Часть карточек является рекламой. Если нужны только органические листинги, необходимо отличать их от спонсорских.

Шаг 2: парсинг листингов с помощью BeautifulSoup

Получив HTML, загрузите его в BeautifulSoup и извлеките каждый товар по его селектору. Google оборачивает каждый результат сетки в контейнер .sh-dgr__grid-result, а отдельные поля находятся во вложенных элементах внутри него. Проверяйте актуальные имена классов в инструментах разработчика браузера на живой странице; приведённые ниже селекторы соответствуют структуре на момент написания.

python
def parse_products(html):
    soup = BeautifulSoup(html, "html.parser")

    products = []
    for item in soup.select(".sh-dgr__grid-result"):
        title_el = item.select_one("h3.tAxDx")
        price_el = item.select_one("span.a8Pemb.OFFNJ")
        seller_el = item.select_one(".aULzUe.IuHnof")
        rating_el = item.select_one(".Rsc7Yb")
        link_el = item.select_one("a.Lq5OHe")

        products.append({
            "title": title_el.get_text(strip=True) if title_el else None,
            "price": price_el.get_text(strip=True) if price_el else None,
            "seller": seller_el.get_text(strip=True) if seller_el else None,
            "rating": rating_el.get_text(strip=True) if rating_el else None,
            "link": "https://www.google.com" + link_el["href"] if link_el else None,
        })

    return products

Каждое поле читается по собственному селектору: h3.tAxDx содержит название, span.a8Pemb.OFFNJ, цену, .aULzUe.IuHnof, продавца или ритейлера, .Rsc7Yb, рейтинг, а якорь a.Lq5OHe несёт ссылку на товар. href, который хранит Google, является относительным, поэтому добавление https://www.google.com в начало превращает его в полный URL. У каждого поля есть защита ... if el else None, поэтому отсутствующий рейтинг или продавец даёт None в записи, а не исключение, которое прервёт весь процесс.

Селекторы устаревают

Имена классов Google, такие как tAxDx и a8Pemb, генерируются и меняются при каждом обновлении фронтенда. Относитесь к приведённым выше селекторам как к отправной точке, а не к договору. Если поле возвращает None для каждого товара, проверьте живую страницу в инструментах разработчика и обновите селектор. Периодическое обновление селекторов, норма для любого рабочего скрапера, а не признак поломки.

Шаг 3: обработка пагинации

Двадцать товаров на одной странице, это демонстрация; мониторинг цен требует полного набора данных. Google Shopping пагинирует с помощью параметра запроса start, смещения в результатах: start=0, первая страница, start=20, вторая, start=40, третья и так далее с шагом в 20. Структура одинакова для каждой страницы, поэтому вы формируете каждый URL, получаете его через Crawling API и разбираете той же функцией. Небольшая пауза между запросами в цикле позволяет длительному процессу работать стабильно.

python
import time

def scrape_multiple_pages(base_url, pages=3):
    all_products = []
    for page in range(pages):
        start_index = page * 20
        paginated_url = f"{base_url}&start={start_index}"
        html = fetch_html(paginated_url)
        if html:
            all_products.extend(parse_products(html))
        time.sleep(3)
    return all_products

Цикл умножает индекс страницы на 20, чтобы получить каждое смещение start, добавляет его к базовому URL и собирает разобранные товары в один плоский список. time.sleep(3) между страницами, наиболее полезная привычка при длительном сборе данных: равномерные запросы позволяют Google воспринимать вас как покупателя, а не бота.

Шаг 4: сборка и экспорт в JSON и CSV

Теперь соедините получение, парсинг и пагинацию в один рабочий скрипт, а затем запишите результаты в JSON и CSV. JSON сохраняет вложенную структуру для кода, который её потребляет; CSV открывается напрямую в таблице, что является форматом, который большинство рабочих процессов мониторинга цен фактически использует.

python
from crawlbase import CrawlingAPI
from bs4 import BeautifulSoup
import json
import csv
import time

crawling_api = CrawlingAPI({"token": "YOUR_CRAWLBASE_TOKEN"})

options = {
    "country": "US",
    "user_agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/123.0.0.0 Safari/537.36",
    "page_wait": 5000,
}

def fetch_html(url):
    response = crawling_api.get(url, options)
    if response["headers"]["cb_status"] != "200":
        print(f"Failed to fetch the page. Status: {response['headers']['cb_status']}")
        return None
    return response["body"].decode("utf-8")

def parse_products(html):
    soup = BeautifulSoup(html, "html.parser")
    products = []
    for item in soup.select(".sh-dgr__grid-result"):
        title_el = item.select_one("h3.tAxDx")
        price_el = item.select_one("span.a8Pemb.OFFNJ")
        seller_el = item.select_one(".aULzUe.IuHnof")
        rating_el = item.select_one(".Rsc7Yb")
        link_el = item.select_one("a.Lq5OHe")
        products.append({
            "title": title_el.get_text(strip=True) if title_el else None,
            "price": price_el.get_text(strip=True) if price_el else None,
            "seller": seller_el.get_text(strip=True) if seller_el else None,
            "rating": rating_el.get_text(strip=True) if rating_el else None,
            "link": "https://www.google.com" + link_el["href"] if link_el else None,
        })
    return products

def scrape_multiple_pages(base_url, pages=3):
    all_products = []
    for page in range(pages):
        paginated_url = f"{base_url}&start={page * 20}"
        html = fetch_html(paginated_url)
        if html:
            all_products.extend(parse_products(html))
        time.sleep(3)
    return all_products

def save_json(data, filename="products.json"):
    with open(filename, "w", encoding="utf-8") as f:
        json.dump(data, f, ensure_ascii=False, indent=4)

def save_csv(data, filename="products.csv"):
    if not data:
        return
    with open(filename, "w", newline="", encoding="utf-8") as f:
        writer = csv.DictWriter(f, fieldnames=data[0].keys())
        writer.writeheader()
        writer.writerows(data)

def main():
    base_url = "https://www.google.com/search?q=louis+vuitton+bags&tbm=shop&num=20"
    products = scrape_multiple_pages(base_url, pages=3)
    if products:
        save_json(products)
        save_csv(products)
        print(f"Saved {len(products)} products to products.json and products.csv")

if __name__ == "__main__":
    main()

Запустите полный скрипт командой python shopping.py. Он обходит три страницы результатов Shopping по запросу "louis vuitton bags", извлекает запись для каждого товара и записывает всё в products.json и products.csv. Чтобы отслеживать другой товар, измените значение q в base_url; остальная часть конвейера обрабатывает всё, что придёт в ответ. Запустите скрипт по расписанию и сравнивайте столбец цен между запусками, это основа системы мониторинга цен.

Как выглядит вывод

Вы получаете чистый список записей о товарах, каждая из которых содержит название, цену, продавца, рейтинг и ссылку, готовых для записи в JSON, CSV или базу данных.

json
[
    {
        "title": "Louis Vuitton Mini Pochette Accessoires Monogram",
        "price": "$760.00",
        "seller": "louisvuitton.com",
        "rating": "4.5",
        "link": "https://www.google.com/shopping/product/11460745201866483383"
    },
    {
        "title": "Louis Vuitton Onthego Empreinte PM Black",
        "price": "$3,568.00",
        "seller": "StockX",
        "rating": null,
        "link": "https://www.google.com/shopping/product/7199001631589324220"
    }
]

CSV-копия содержит одну строку на товар с колонками title,price,seller,rating,link и строкой заголовка, поэтому она открывается корректно в любом табличном редакторе. Отсутствующее поле выводится как пустая ячейка в CSV и null в JSON, что соответствует рейтингу второго листинга в примере выше.

Сохранение доступности при масштабировании

Даже при наличии доверенного IP Google отслеживает трафик, характерный для скраперов, и Shopping не является исключением. Несколько привычек помогут поддерживать работу в стабильном режиме.

  • Регулируйте частоту запросов. Интенсивный обход страниц результатов в плотном цикле, самый быстрый способ получить блокировку. time.sleep между страницами существует не просто так; оставьте его и варьируйте запросы вместо того, чтобы непрерывно обходить один термин.
  • Используйте ротацию. Пул резидентских IP распределяет запросы между многими адресами реальных пользователей, не превышая лимит по одному адресу. Crawling API делает это за вас; при самостоятельной сборке стека именно этому нужно уделить особое внимание.
  • Фиксируйте нужную страну. Цены и продавцы различаются в зависимости от региона. Установите параметр country на нужный рынок, чтобы данные соответствовали тому, что видит местный покупатель.
  • Проверяйте страницы заново, когда поля перестают парситься. Google периодически обновляет разметку. Если поле перестало парситься, откройте живую страницу в инструментах разработчика и обновите селектор.

Более широкие подходы описаны в руководстве как парсить сайты без блокировок. Если вы встраиваете это в регулярную задачу отслеживания цен, наше руководство по веб-скрапингу для ценовой аналитики рассказывает, как превратить сырые листинги в полезный сигнал, а более широкое руководство по веб-скрапингу в e-commerce распространяет этот подход на другие магазины. Чтобы парсить обычные результаты поиска Google, а не вкладку Shopping, смотрите как парсить страницы поиска Google.

Законно ли парсить Google Shopping?

Разрешённость парсинга Google Shopping зависит от условий использования Google, вашей юрисдикции и того, что вы делаете с данными. Условия Google ограничивают автоматизированный доступ, поэтому парсинг может противоречить этим условиям вне зависимости от тщательности вашего инструментария. Ни один из приведённых здесь кодов этого не изменяет; он лишь делает работающей техническую сторону. Ознакомьтесь с условиями Google и его robots.txt и соблюдайте их как границу того, что вы собираете.

Несколько правил, которых стоит придерживаться. Собирайте только публичные данные листингов: названия товаров, цены, продавцов, рейтинги и ссылки, которые любой может увидеть на странице результатов Shopping без аккаунта. Поддерживайте объём запросов достаточно низким, чтобы не нагружать серверы Google, регулируйте частоту сбора вместо непрерывной работы и фиксируйте страну на нужном рынке. Не перепубликуйте изображения товаров Google или защищённые авторским правом медиаматериалы оптом и держитесь подальше от всего, что находится за логином или персональных данных, которых в этом учебнике нет.

Если вам нужны данные Shopping в масштабе или форме, которые публичный парсинг не может обоснованно поддержать, Google предлагает официальные пути. Content API для Shopping, а также API для продавцов и рекламы являются санкционированными способами программного управления и чтения данных о товарах, и официальное соглашение, правильный путь, когда проект перерастает скромный, публичный, дозированный сбор. Более совершенный скрапер не заменяет соглашение о данных.

Итоги

Ключевые выводы

  • Google Shopping отрисовывается через JS и учитывает регион. Простой запрос возвращает стену согласия или неправильную валюту, поэтому нужен отрисованный запрос с доверенного резидентского IP в правильной стране.
  • Crawling API получает страницу через реальный IP. Передайте ему URL Shopping с фиксированной страной, он ротирует резидентские IP и отрисовывает сетку на стороне сервера, возвращая готовый HTML для парсинга.
  • BeautifulSoup выполняет извлечение. Выберите каждый .sh-dgr__grid-result, затем прочитайте название, цену, продавца, рейтинг и ссылку из него; ожидайте, что генерируемые имена классов будут меняться.
  • Пагинация через смещение start. Увеличивайте start с шагом 20 для обхода результатов вглубь и делайте паузы между страницами.
  • Экспорт в JSON и CSV. JSON сохраняет структуру для кода; CSV открывается в таблице, что использует большинство рабочих процессов мониторинга цен. Работайте только с публичными данными и соблюдайте ToS и robots.txt Google.

Часто задаваемые вопросы

Почему простой запрос не работает или возвращает неправильную страницу в Google Shopping?

Google отрисовывает большую часть сетки Shopping с помощью JavaScript и адаптирует ответ в зависимости от запрашивающего IP и региона, поэтому запрос с зарубежного адреса дата-центра может вернуть стену согласия, неправильную валюту или неполный контент вместо листингов из вашего браузера. Кроме того, Google помечает трафик, не похожий на реальный браузер. Получение через Crawling API, использующий ротирующие резидентские IP и отрисовывающий страницу, делает запрос похожим на обычного покупателя, позволяя получить реальные результаты.

Какие поля можно извлечь из Google Shopping?

В этом учебнике из каждой карточки товара извлекаются пять полей: название, цена, продавец или ритейлер, рейтинг (если указан) и ссылка на страницу товара в Shopping. Парсер можно расширить, добавив больше селекторов для получения изображений или текста о доставке. Работайте только с публичными данными листингов и не обращайтесь к тому, что находится за логином.

Как обрабатывать пагинацию в Google Shopping?

Используйте параметр запроса start, смещение в результатах: start=0, первая страница, start=20, вторая, start=40, третья и так далее с шагом в 20. Формируйте каждый URL страницы со смещением, получайте его через Crawling API, разбирайте той же функцией и делайте паузу в несколько секунд между запросами для дозированного сбора.

Можно ли использовать это для мониторинга цен?

Да, это основной сценарий использования. Запускайте скрипт по расписанию, экспортируйте результаты в CSV и сравнивайте столбец цен между запусками, чтобы отслеживать повышения, снижения и появление новых продавцов для нужных товаров. Фиксация параметра country обеспечивает сопоставимость цен с интересующим вас рынком. Наше руководство по веб-скрапингу для ценовой аналитики подробнее рассказывает о том, как превратить сырые данные в полезный сигнал.

Селекторы ничего не возвращают. Что изменилось?

Скорее всего, разметка Google. Имена классов, такие как tAxDx и a8Pemb, генерируются и меняются при каждом обновлении фронтенда, поэтому селекторы, работавшие в прошлом месяце, могут перестать работать. Проверьте живую страницу Shopping в инструментах разработчика браузера и обновите селекторы. Периодическое обновление селекторов, норма для любого рабочего скрапера.

Есть ли официальный API у Google Shopping?

Да. Google предлагает Content API для Shopping, а также API для продавцов и рекламы, которые позволяют разработчикам программно управлять листингами товаров, рекламными кампаниями и данными о производительности. Если вашему проекту нужны данные Shopping в масштабе или в санкционированной форме, эти официальные конечные точки являются правильным путём вместо публичного парсинга.

Начать создавать

Обходите любой сайт в масштабе, без борьбы с инфраструктурой.

Crawlbase берёт на себя прокси, отпечатки и CAPTCHA, чтобы ваша команда выпускала конвейеры данных вместо поддержки обвязки краулинга. 1 000 запросов бесплатно, без карты.

Самообслуживание · Звонок отдела продаж не требуется · Доступны корпоративные объёмы краулинга