Введите любой популярный запрос на Amazon, и первые результаты, которые вы увидите, редко окажутся самыми органичными. Это Sponsored Products: объявления с оплатой за клик (PPC), на которые бренды делают ставки, чтобы занять верх страницы результатов, каждое помечено небольшой пометкой "Sponsored" или "Ad". Эти размещения публичны, и паттерн того, какие товары рекламируются по каким запросам, это прямое окно в стратегию конкурентов, приоритеты рекламных расходов и в то, за какие термины борется категория.
Это руководство показывает, как парсить данные Amazon PPC-объявлений на Python. Вы создадите небольшой работающий скрапер, который получает отрисованную страницу результатов поиска Amazon через Crawling API, разбирает из сетки только спонсируемые размещения с помощью BeautifulSoup и вытаскивает чистую запись для каждого объявления: название, цену, позицию на странице и ссылку на товар. Весь разбор ограничен публичными данными страницы поиска, которые видит любой покупатель, а раздел о законности ближе к концу не для галочки, так что прочитайте его, прежде чем направлять этот скрипт на любой реальный объём.
Что вы построите
Python-скрипт, который принимает поисковый запрос, получает отрисованную страницу результатов Amazon через Crawling API, изолирует спонсируемые карточки от органичных и извлекает структурированную запись на каждое объявление. В качестве сквозного примера мы используем поиск по headphones и вытащим из каждой спонсируемой карточки следующие поля:
- Название текст названия рекламируемого товара.
- Цена указанная цена, показанная на спонсируемой карточке.
- Позиция где объявление стоит в порядке результатов, чтобы вы могли видеть размещения в верху страницы против размещений ниже.
- Ссылка URL на собственную страницу с подробной информацией о рекламируемом товаре.
- Ключевое слово поисковый термин, по которому появилось объявление, переносимый дальше, чтобы вы могли группировать результаты по запросу.
Почему обычный запрос не срабатывает на Amazon
Если запросить URL поиска Amazon голым HTTP-клиентом, вы получите ответ со статусом 200 и почти без данных о товарах в теле. Против вас работают две вещи. Во-первых, Amazon загружает свою сетку поиска динамически: начальный HTML это в основном оболочка, а важный контент заполняется через JavaScript и Ajax, когда страница выполняется в браузере. Сохраните сырой запрос в файл, и вы обнаружите, что спонсируемых карточек там просто нет. Во-вторых, Amazon быстро помечает автоматизированный трафик. IP-адреса дата-центров и паттерны запросов, которые не выглядят как настоящий браузер, получают проверку CAPTCHA или блокировку ещё до того, как они доберутся до отрисованных списков.
Так что рабочему скраперу объявлений Amazon нужны две вещи в одном запросе: браузер, который действительно отрисовывает страницу, и IP-адрес, который платформа воспринимает как реального покупателя. Вы можете собрать это самостоятельно из headless-браузера и пула ротируемых резидентных прокси, но сшить их вместе и поддерживать в рабочем состоянии и есть основная часть работы. Crawling API объединяет и то и другое в один вызов: вы отправляете ему URL с JavaScript-токеном, он отрисовывает страницу за доверенным резидентным IP и возвращает готовый HTML, который вам останется разобрать. Подробнее о том, почему отрисовываемые на клиенте сайты сопротивляются обычным запросам, смотрите в как обходить JavaScript-сайты.
Crawlbase предлагает два типа токенов. Обычный токен (TCP) получает статический HTML; JavaScript (JS) токен сначала отрисовывает страницу в настоящем браузере. Amazon сильно опирается на JavaScript для динамического контента, поэтому здесь вам нужен JS-токен. Обычный токен возвращает ту же пустую оболочку, что и обычный запрос, и из неё нечего разбирать.
Предварительные требования
Прежде чем писать код, вам нужно подготовить несколько вещей. Ни одна из них не займёт много времени.
Базовый Python. Вы должны уверенно писать и запускать Python-скрипт и устанавливать пакеты через pip. Если язык для вас в новинку, официальная документация Python и любой курс для начинающих доведут вас до уровня, который предполагает этот туториал.
Python 3.8 или новее. Подтвердите свою версию командой python --version. Если его у вас нет, установите его с python.org или через дистрибутив вроде Anaconda.
Учётная запись Crawlbase и JS-токен. Зарегистрируйте бесплатную учётную запись, откройте дашборд и скопируйте свой JavaScript (JS) токен со страницы документации учётной записи. Бесплатный тариф включает до 20 000 запросов без карты, чего с лихвой хватит, чтобы пройти это руководство. Относитесь к токену как к паролю: он аутентифицирует ваши запросы, поэтому держите его вне системы контроля версий.
Настройте проект
Создайте виртуальное окружение, чтобы зависимости проекта оставались изолированными, затем установите библиотеки, которые нужны скраперу.
python --version python -m venv amazon_env source amazon_env/bin/activate pip install crawlbase beautifulsoup4 pandas
В Windows активируйте окружение командой amazon_env\Scripts\activate вместо строки source. Три зависимости делают всю работу: crawlbase это официальный клиент для Crawling API, beautifulsoup4 разбирает возвращённый HTML, чтобы вы могли вытащить каждое поле по CSS-селектору, а pandas помогает вам организовать собранные объявления для анализа ключевых слов в конце.
Понимание спонсируемых размещений Amazon
Страница результатов поиска Amazon это сетка карточек товаров. Большинство из них органичные списки, ранжированные по релевантности, но среди них вкраплены Sponsored Products: PPC-объявления. Визуально они выглядят как любая другая карточка, с названием, ценой, изображением и пометкой "Sponsored". Структурно Amazon оборачивает спонсируемые карточки так, что вы можете отличить их от органичных, и это именно то, что позволяет вам скрапить только объявления.
Прежде чем писать селекторы, откройте страницу поиска в браузере, кликните правой кнопкой по спонсируемой карточке и выберите «Просмотреть код». Спонсируемые карточки живут внутри контейнеров, которые несут класс AdHolder рядом с обычными атрибутами результата data-asin. Название сидит в якоре внутри заголовка карточки, а цена выставлена через разметку a-price от Amazon. Это те зацепки, на которые вы нацеливаетесь. Имена классов Amazon смещаются со временем, но маркер AdHolder и структура a-price оказались устойчивыми, так что опирайтесь на них.
Шаг 1: Получите отрисованную страницу поиска
Начните с получения готовой страницы. Импортируйте класс CrawlingAPI, инициализируйте его своим JS-токеном, постройте URL поиска из ключевого слова и запросите его с параметрами ожидания, которые нужны динамической сетке Amazon. Проверка кода статуса перед разбором делает сбои громкими, а не молчаливыми.
from crawlbase import CrawlingAPI # Amazon is JavaScript-rendered, so use your JS token here api = CrawlingAPI({"token": "YOUR_CRAWLBASE_TOKEN"}) def crawl(page_url): options = {"page_wait": 2000, "ajax_wait": "true"} response = api.get(page_url, options) if response["status_code"] == 200: return response["body"].decode("latin1") print(f"Request failed: {response['status_code']}") return None if __name__ == "__main__": keyword = "headphones" search_url = f"https://www.amazon.com/s?k={keyword}" html = crawl(search_url) print(html[:500] if html else "No HTML returned")
Два параметра ожидания важны для динамической цели вроде этой. ajax_wait сообщает API, что нужно дождаться окончания загрузки асинхронного контента, а page_wait выдерживает фиксированное число миллисекунд после загрузки, чтобы поздно отрисовываемая сетка появилась до того, как страница будет захвачена. Две секунды это разумное начало; повысьте значение, если карточки возвращаются отсутствующими. Тело декодируется как latin1, потому что страницы Amazon примешивают символы, на которых строгое декодирование UTF-8 может споткнуться, а latin1 обрабатывает их без ошибок. Запустите скрипт, и вы должны увидеть реальную разметку товаров, а не пустую оболочку, которую возвращает обычный запрос. Это подтверждает, что отрисовка работает, прежде чем вы напишете хоть один селектор.
Amazon нужна отрисованная страница за доверенным IP в одном вызове, и именно поэтому обычный запрос выше возвращает пустую оболочку. Crawling API принимает JS-токен, выполняет страницу в настоящем браузере, ротирует резидентные IP на стороне сервера и отдаёт вам готовый HTML, так что вы избегаете запуска флота headless-браузеров и пула прокси самостоятельно. Сначала направьте его на ключевое слово на бесплатном тарифе.
Шаг 2: Разберите спонсируемые карточки с помощью BeautifulSoup
Имея на руках отрисованный HTML, загрузите его в BeautifulSoup и выберите только спонсируемые карточки. Это ключевое отличие от обычного скрапа поиска: вместо того чтобы хватать каждый результат, вы нацеливаетесь на контейнеры AdHolder, так что собираете объявления и ничего больше. Затем вытащите каждое поле по его селектору, перенесённому прямо из разметки живой страницы. Оберните каждую карточку в try/except, чтобы одно неправильно сформированное объявление не уронило прогон.
from bs4 import BeautifulSoup def parse_ads(html, keyword): soup = BeautifulSoup(html, "html.parser") # Select only sponsored (PPC) cards, not organic results ads = soup.select( '.AdHolder div[data-asin], ' 'div[data-asin][data-component-type="s-search-result"].AdHolder' ) results = [] for position, ad in enumerate(ads, start=1): try: # Price inside the ad card price_el = ad.select_one("span.a-price span.a-offscreen") price = price_el.text.strip() if price_el else "Price not found" # Title inside the ad card title_el = ad.select_one( "div.a-section h2 a.a-link-normal span, " "div.a-section a.a-link-normal span.a-offscreen" ) title = title_el.text.strip() if title_el else "Title not found" # Link to the advertised product page link_el = ad.select_one("h2 a.a-link-normal, a.a-link-normal") link = None if link_el and link_el.get("href"): link = "https://www.amazon.com" + link_el["href"] results.append({ "keyword": keyword, "position": position, "title": title, "price": price, "link": link, }) except Exception as e: print(f"Skipped a card: {e}") return results
Селектор, который изолирует объявления, это сердце этого скрапера. .AdHolder div[data-asin] сопоставляется со спонсируемыми карточками, оставляя органичные результаты нетронутыми, так что parse_ads когда-либо видит только PPC-размещения. Цена приходит из скрытого span.a-offscreen внутри блока a-price от Amazon, который хранит чистое числовое значение, а название читается из якоря заголовка карточки с резервным селектором для макетов, которые выставляют его иначе. enumerate(..., start=1) записывает позицию каждого объявления в порядке результатов, и это то, что превращает плоский список в аналитику размещений: позиция 1 это ставка в верху страницы, более низкие числа это более дорогая недвижимость. Каждое отсутствующее поле деградирует до сигнальной строки или None, а не роняет цикл. Если вы хотите освежить сам синтаксис селекторов, руководство по использованию BeautifulSoup в Python охватывает его подробно.
Имена классов и структура карточек Amazon меняются без предупреждения. Маркер AdHolder, блок цены a-price и якорь заголовка выше это отправной шаблон, а не контракт. Когда названия или цены возвращаются сигналом «не найдено» для каждого объявления, заново осмотрите живую спонсируемую карточку в инструментах разработчика браузера и обновите селектор. Периодическое обслуживание селекторов это норма для любого продакшен-скрапера, а не признак того, что что-то сломалось.
Шаг 3: Соберите всё вместе и проанализируйте ключевое слово
Теперь свяжите получение и разбор в один работающий скрипт, затем добавьте отдачу: небольшой анализ, который превращает сырой список объявлений в аналитику конкурентов. Получите отрисованную страницу поиска, изолируйте спонсируемые карточки и загрузите записи в pandas DataFrame, чтобы вы могли видеть, какие товары рекламируются по ключевому слову и в каких ценовых точках.
import json import pandas as pd from bs4 import BeautifulSoup from crawlbase import CrawlingAPI api = CrawlingAPI({"token": "YOUR_CRAWLBASE_TOKEN"}) def crawl(page_url): options = {"page_wait": 2000, "ajax_wait": "true"} response = api.get(page_url, options) if response["status_code"] == 200: return response["body"].decode("latin1") print(f"Request failed: {response['status_code']}") return None def parse_ads(html, keyword): soup = BeautifulSoup(html, "html.parser") ads = soup.select( '.AdHolder div[data-asin], ' 'div[data-asin][data-component-type="s-search-result"].AdHolder' ) results = [] for position, ad in enumerate(ads, start=1): try: price_el = ad.select_one("span.a-price span.a-offscreen") price = price_el.text.strip() if price_el else "Price not found" title_el = ad.select_one( "div.a-section h2 a.a-link-normal span, " "div.a-section a.a-link-normal span.a-offscreen" ) title = title_el.text.strip() if title_el else "Title not found" link_el = ad.select_one("h2 a.a-link-normal, a.a-link-normal") link = None if link_el and link_el.get("href"): link = "https://www.amazon.com" + link_el["href"] results.append({ "keyword": keyword, "position": position, "title": title, "price": price, "link": link, }) except Exception as e: print(f"Skipped a card: {e}") return results def analyze(ads): if not ads: print("No sponsored ads found for this keyword.") return df = pd.DataFrame(ads) print(f"Sponsored placements found: {len(df)}") print("\nTop-of-page advertisers:") print(df[["position", "title", "price"]].head()) return df def main(): keyword = "headphones" search_url = f"https://www.amazon.com/s?k={keyword}" html = crawl(search_url) if not html: return ads = parse_ads(html, keyword) print(json.dumps(ads, indent=2)) df = analyze(ads) if df is not None: df.to_csv("amazon_ppc_ads.csv", index=False) if __name__ == "__main__": main()
Шаг analyze это то, что делает это инструментом рекламной аналитики, а не сырой выгрузкой. Загрузка записей в DataFrame позволяет вам сортировать по позиции, чтобы видеть, кто выигрывает верхние ставки, группировать по цене, чтобы прочитать конкурентный ценовой диапазон, и записывать всё в amazon_ppc_ads.csv для отслеживания во времени. Запустите то же ключевое слово по расписанию, и различия скажут вам, когда новый конкурент входит в аукцион или существующий меняет приоритет своих ставок. Если вы хотите подать эти цены в более широкую модель, руководство по использованию веб-скрапинга для ценовой аналитики показывает, куда такого рода данные идут дальше.
Как выглядит вывод
Запустите полный скрипт командой python scraper.py, и вы получите чистый список спонсируемых записей, по одной на объявление, плюс CSV и короткую сводку. Форма JSON выглядит так:
[ { "keyword": "headphones", "position": 1, "title": "Wireless Bluetooth Headphones, Over-Ear, 40H Playtime", "price": "$39.99", "link": "https://www.amazon.com/dp/..." }, { "keyword": "headphones", "position": 2, "title": "Noise Cancelling Headphones, Wired and Wireless", "price": "$59.95", "link": "https://www.amazon.com/dp/..." } ]
Каждая запись несёт ключевое слово, позицию на странице, рекламируемое название и цену и ссылку на страницу товара. Этого достаточно, чтобы ответить на главный вопрос конкурентной аналитики: для любого термина, который вас интересует, какие товары платят за то, чтобы сидеть в верху, и в каком ценовом диапазоне они конкурируют.
Масштабирование по ключевым словам и страницам
Одно ключевое слово на одной странице это демо. Реальная ценность приходит от запуска списка ключевых слов по расписанию и отслеживания того, как смещается набор рекламодателей. Пройдите свои целевые термины в цикле, соскребите спонсируемые карточки по каждому и объедините результаты, чтобы один CSV содержал полную конкурентную картину.
import time def scrape_keywords(keywords): all_ads = [] for keyword in keywords: url = f"https://www.amazon.com/s?k={keyword}" html = crawl(url) if not html: continue ads = parse_ads(html, keyword) all_ads.extend(ads) print(f"{keyword}: {len(ads)} sponsored placements") time.sleep(2) return all_ads keywords = ["headphones", "wireless earbuds", "bluetooth speaker"] ads = scrape_keywords(keywords)
Пауза time.sleep(2) между ключевыми словами размеряет прогон, так что вы не долбите поиск в плотном цикле, что есть самый быстрый способ получить троттлинг. Чтобы обойти дополнительные страницы результатов для одного ключевого слова, Amazon пагинирует поиск параметром &page= на URL, так что вы увеличиваете его тем же способом и останавливаетесь, когда страница возвращает ноль спонсируемых карточек. Держите предел скромным: самые ценные рекламные размещения и так сидят на первой или двух страницах.
Как оставаться разблокированным
Даже когда отрисовка обработана, Amazon отслеживает трафик в форме скрапера. Несколько привычек поддерживают прогон в здоровом состоянии, и они применимы к любой трудной коммерческой цели.
-
Размеряйте свои запросы. Распределяйте запросы с задержкой между ключевыми словами и страницами, вместо того чтобы обходить на полной скорости.
time.sleepв цикле это пол, а не потолок. - Опирайтесь на ротацию. Пул резидентных IP распределяет запросы по множеству адресов реальных пользователей, так что ни один из них не упирается в лимит частоты. Crawling API делает это за вас; если вы собираете свой собственный стек, это та часть, которую нужно сделать правильно.
- Читайте коды статусов. Прогон, который начинает возвращать проверки или ошибки, говорит вам, что текущего темпа или уровня IP больше недостаточно. Воспринимайте это как сигнал отступить, а не как шум, который можно игнорировать.
Более широкий план действий по поддержанию здоровья скрапера против защищённых сайтов смотрите в как скрапить сайты, не попадая в блокировку.
Законно ли скрапить рекламные данные Amazon?
Разрешён ли скрапинг Amazon, зависит от Условий использования Amazon, вашей юрисдикции и того, что вы делаете с данными. Условия Amazon ограничивают автоматизированный доступ, поэтому скрапинг может вступать в противоречие с этими условиями, как бы аккуратен ни был ваш инструментарий. Ничего из кода здесь этого не меняет; он лишь заставляет техническую часть работать. Прочитайте Условия использования Amazon и его robots.txt и относитесь к обоим как к границе того, что вы собираете.
Несколько правил, которых стоит держаться. Спонсируемое название, цена, позиция и ссылка на товар, которые вытаскивает этот скрапер, это публичные данные: любой, кто запускает тот же поиск, видит те же объявления, без требования учётной записи. Оставайтесь на этой публичной, обращённой к рекламе поверхности. Уважайте заявленные Amazon ожидания по частоте и держите объём запросов достаточно низким, чтобы не нагружать его серверы. Избегайте персональных данных, включая всё, что привязано к идентифицируемым покупателям, рецензентам или продавцам сверх того, что публично указано на странице результатов, и не перераспределяйте оптом защищённые авторским правом изображения или описания товаров. Использование рекламных данных для собственного конкурентного анализа это очень отличная вещь от переопубликования контента Amazon.
Это руководство намеренно ограничено публичными спонсируемыми размещениями на страницах поиска, потому что именно эта черта удерживает работу в защитимых рамках. Оно не охватывает ничего за логином, данные seller-central или управления кампаниями, частные метрики учётной записи другого рекламодателя, платёжные потоки или любую попытку обойти аутентификацию. Данные "Sponsored" на странице, которые вы собираете здесь, это публичный рекламный след конкурента, а не его внутренние цифры кампаний. Для лицензированного или массового доступа Amazon предлагает официальные API рекламы и товаров, и это правильный инструмент, когда вам нужны большие объёмы, гарантированная структура или коммерческие права. Если вашему проекту нужно больше, чем публичные рекламные размещения, правильный путь это официальный API или соглашение по данным, а не более хитрый скрапер.
Ключевые выводы
- Спонсируемые размещения это публичная аналитика конкурентов. То, какие товары рекламируются по ключевому слову, на какой позиции и по какой цене, видно любому покупателю и раскрывает реальную рекламную стратегию.
- Поиск Amazon отрисовывается на JavaScript. Обычный запрос возвращает пустую оболочку, поэтому вы должны отрисовать страницу JS-токеном, прежде чем хоть одна спонсируемая карточка появится для разбора.
-
Селектор AdHolder изолирует объявления. Нацеливание на
.AdHolder div[data-asin]собирает только PPC-карточки, а селекторыa-priceи якоря заголовка вытаскивают из каждой название, цену и ссылку. -
Позиция превращает список в данные о размещении. Запись порядка каждого объявления через
enumerate, затем загрузка в pandas, позволяет вам отслеживать ставки в верху страницы и ценовые диапазоны по ключевым словам во времени. - Оставайтесь на публичных данных. Уважайте Условия использования и robots.txt Amazon, предпочитайте официальный API Amazon для лицензированных или массовых данных и никогда не трогайте учётные записи, внутренности кампаний или персональную информацию.
Часто задаваемые вопросы
Что такое Amazon PPC-реклама?
Amazon PPC (оплата за клик) реклама позволяет продавцам и брендам продвигать товары внутри результатов поиска и страниц товаров Amazon. Эти Sponsored Products помечены "Sponsored" или "Ad", и рекламодатель платит только когда покупатель кликает. Поскольку объявления управляются ставками, набор товаров, рекламирующихся по данному ключевому слову, это живое чтение того, какие бренды тратят, чтобы бороться за этот термин.
Почему обычный запрос не возвращает объявлений от Amazon?
Потому что Amazon загружает свою сетку поиска динамически с помощью JavaScript и Ajax. Начальный HTML это в основном оболочка, поэтому сырой HTTP-запрос возвращает статус 200 со спонсируемыми и органичными карточками, обе пустые. Чтобы получить реальные данные, вам нужно сначала отрисовать страницу, и это то, что обеспечивает за вас JS-токен Crawling API, прежде чем BeautifulSoup её разберёт.
Как мне скрапить только спонсируемые объявления, а не органичные результаты?
Amazon оборачивает спонсируемые карточки в контейнеры, несущие класс AdHolder. Выбор по .AdHolder div[data-asin] сопоставляется только с этими карточками, так что ваш парсер собирает PPC-размещения и целиком пропускает органичные списки. Из каждой карточки объявления вы затем читаете название из её якоря заголовка, цену из блока a-price и href для ссылки на товар.
Моё название или цена возвращаются как «не найдено». Что изменилось?
Почти наверняка разметка Amazon. Её имена классов и структура карточек меняются без предупреждения, и селекторы a-price или якоря заголовка выше могут перестать сопоставляться. Заново осмотрите живую спонсируемую карточку в инструментах разработчика браузера, подтвердите обёртку AdHolder и внутренние селекторы цены и названия и обновите их. Периодическое обслуживание селекторов это норма для любого продакшен-скрапера.
Что я могу делать со собранными рекламными данными Amazon?
Отслеживать рекламу конкурентов во времени: какие товары входят в спонсируемый набор по ключевому слову или покидают его, где они размещаются и в каком ценовом диапазоне конкурируют. Запускайте те же ключевые слова по расписанию, и различия выводят на поверхность новых участников и сдвиги приоритетов ставок. Поля позиции и цены подаются напрямую в дашборды рекламной и ценовой аналитики.
Нужен ли мне обычный токен или JS-токен для Amazon?
JS-токен. Обычный токен получает статический HTML, который на Amazon это та же пустая оболочка, что и обычный запрос. JS-токен отрисовывает страницу в настоящем браузере, прежде чем отдать HTML, так что спонсируемые карточки присутствуют, когда запускается ваш парсер. Сочетайте его с параметрами page_wait и ajax_wait, чтобы у динамической сетки было время закончить загрузку.
Обходите любой сайт в масштабе, без борьбы с инфраструктурой.
Crawlbase берёт на себя прокси, отпечатки и CAPTCHA, чтобы ваша команда выпускала конвейеры данных вместо поддержки обвязки краулинга. 1 000 запросов бесплатно, без карты.
