Отзывы о товарах Amazon, один из богатейших публичных сигналов в открытой сети. Звёздный рейтинг, заголовок, текст и дата каждого отзыва в совокупности составляют постоянно пополняемую летопись того, что думают реальные покупатели о товаре. Эти данные лежат в основе анализа тональности, исследований товаров и сравнения конкурентов, поэтому командам нужен чистый структурированный поток, а не ручная прокрутка страницы.
Это руководство показывает, как парсить отзывы Amazon на Python. Вы создадите небольшой готовый к запуску парсер, который получает страницу отзывов о товаре через Crawling API, разбирает каждый отзыв с помощью BeautifulSoup, обходит пагинацию и экспортирует результаты в JSON и CSV. Руководство ограничивается публичным текстом отзывов, которые Amazon показывает любому посетителю, а юридический раздел ближе к концу, не формальность, поэтому прочтите его перед запуском на реальных объёмах.
Что вы создадите
Скрипт на Python, который принимает URL страницы отзывов о товаре Amazon, получает отрендеренную страницу через Crawling API и извлекает структурированную запись по каждому отзыву. В качестве примера используется Meta Quest Pro, из которого извлекаются следующие поля каждого блока отзыва:
- Имя рецензента публичное отображаемое имя, указанное в отзыве.
- Рейтинг количество звёзд, например "4.0 out of 5 stars".
- Заголовок короткий заголовок, который рецензент дал отзыву.
- Текст отзыва полный написанный отзыв.
- Дата строка вида "Reviewed in the United States on ...".
Скрипт собирает эти записи со всех страниц отзывов и записывает их в amazon_reviews.json и amazon_reviews.csv, готовые для модели тональности, таблицы или базы данных.
Почему обычный запрос не работает на Amazon
Если направить простой HTTP-клиент на URL страницы отзывов Amazon, вы редко получаете сами отзывы. Amazon, один из наиболее защищённых сайтов в сети от автоматизированного трафика. IP датацентра или запрос, не похожий на настоящий браузер, встречает CAPTCHA, промежуточную страницу "Robot Check" или прямую блокировку ещё до того, как достигает блоков с отзывами. Даже если запрос проходит, части страницы рендерятся через JavaScript, поэтому обычный запрос может вернуть оболочку вместо готовой разметки.
Поэтому работающий парсер отзывов Amazon в одном запросе требует двух вещей: браузера, который реально рендерит страницу, и IP, который платформа воспринимает как настоящего покупателя. Можно собрать это самостоятельно с headless-браузером плюс пулом ротирующих резидентских прокси, но сборка и поддержание этой связки составляет большую часть работы. Crawling API объединяет и то, и другое в одном вызове: вы отправляете ему URL, он рендерит страницу за доверенным резидентским IP, ротирует адреса за вас и возвращает готовый HTML для разбора BeautifulSoup.
Crawlbase может возвращать либо сырой HTML для самостоятельного разбора, либо предварительно разобранный JSON через встроенный парсер amazon-product-reviews Scraper API. В этом руководстве HTML разбирается с помощью BeautifulSoup, чтобы вы видели, какие именно селекторы соответствуют каждому полю, а затем указывается, где маршрут с авторазбором избавляет от этого шага.
Предварительные требования
Перед написанием кода нужно подготовить несколько вещей. Это не займёт много времени.
Базовые знания Python. Вы должны уметь писать и запускать скрипт на Python и устанавливать пакеты через pip. Если язык для вас нов, вводный материал парсинг сайта на Python и любой курс для начинающих доведут вас до уровня, который предполагает это руководство.
Python 3.8 или выше. Проверьте версию командой python --version. Если Python не установлен, скачайте его с python.org или через дистрибутив вроде Anaconda.
Аккаунт Crawlbase и токен. Зарегистрируйтесь, откройте панель управления и скопируйте токен со страницы документации аккаунта. Crawlbase даёт до 20 000 бесплатных запросов без необходимости вводить карту, и вы платите только за успешные запросы. Обращайтесь с токеном как с паролем: он аутентифицирует ваши запросы, поэтому не включайте его в систему контроля версий.
Настройка проекта
Создайте виртуальное окружение для изоляции зависимостей проекта, затем установите две библиотеки, которые нужны парсеру.
python --version python -m venv amazon_env source amazon_env/bin/activate pip install crawlbase beautifulsoup4
В Windows активируйте окружение командой amazon_env\Scripts\activate вместо строки с source. Две зависимости выполняют основную работу: crawlbase, официальный клиент Crawling API, а beautifulsoup4 разбирает возвращаемый HTML, позволяя извлекать каждое поле из блока отзыва по CSS-селектору.
Понимание структуры страницы отзывов Amazon
Перед написанием селекторов откройте страницу отзывов о товаре в браузере, кликните правой кнопкой на один отзыв и выберите «Просмотр кода». Amazon оборачивает каждый отзыв в контейнер с атрибутом data-hook="review" и предоставляет доступ к отдельным полям через стабильные атрибуты data-hook внутри этого контейнера. Эти хуки значительно долговечнее имён утилитарных классов Amazon, поэтому ориентируйтесь на них, где это возможно.
Нужные поля соответствуют следующим хукам внутри каждого блока отзыва:
-
Имя рецензента элемент
span.a-profile-name. -
Рейтинг
[data-hook="review-star-rating"](илиreview-star-rating-view-pointв некоторых вариантах вёрстки). -
Заголовок
[data-hook="review-title"]. -
Текст отзыва
[data-hook="review-body"]. -
Дата
[data-hook="review-date"].
Шаг 1: Получить отрендеренную страницу отзывов
Начните с получения готовой страницы. Импортируйте класс CrawlingAPI, инициализируйте его с токеном, укажите URL страницы отзывов о товаре и запросите её. Проверка кода статуса перед разбором делает сбои заметными, а не молчаливыми.
from crawlbase import CrawlingAPI api = CrawlingAPI({"token": "YOUR_CRAWLBASE_TOKEN"}) REVIEWS_URL = ( "https://www.amazon.com/Meta-Quest-Pro-Oculus/product-reviews/" "B09Z7KGTVW/?reviewerType=all_reviews" ) def crawl(page_url): options = {"ajax_wait": "true", "page_wait": 3000} 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__": html = crawl(REVIEWS_URL) print(html[:500] if html else "No HTML returned")
Два параметра ожидания помогают при асинхронной загрузке частей страницы. ajax_wait указывает API дождаться завершения загрузки асинхронного содержимого, а page_wait делает дополнительную паузу на фиксированное число миллисекунд после загрузки, чтобы блоки с отзывами, рендерящиеся с задержкой, появились до захвата страницы. Тело декодируется как latin1, поскольку страницы Amazon содержат символы, при декодировании которых строгий UTF-8 может давать ошибки. Запустите скрипт и вы должны увидеть реальную разметку отзывов, а не страницу Robot Check. Это подтверждает прохождение запроса до написания первого селектора.
Именно страница Robot Check встречает обычный запрос на Amazon. Crawling API рендерит страницу в реальном браузере, ротирует резидентские IP на стороне сервера и возвращает готовый HTML в одном вызове, поэтому вам не нужно запускать собственный headless-флот и пул прокси. Сначала укажите URL отзывов на бесплатном тарифе, затем масштабируйтесь.
Шаг 2: Разобрать отзывы с помощью BeautifulSoup
Имея отрендеренный HTML, загрузите его в BeautifulSoup, найдите каждый блок отзыва и извлеките поля по их селекторам data-hook. Оберните каждый блок в try/except, чтобы один некорректный отзыв не прерывал выполнение.
from bs4 import BeautifulSoup def text_of(block, selector): el = block.select_one(selector) return el.get_text(strip=True) if el else None def parse_reviews(html): soup = BeautifulSoup(html, "html.parser") blocks = soup.select('div[data-hook="review"]') reviews = [] for block in blocks: try: reviews.append({ "reviewer_name": text_of(block, "span.a-profile-name"), "rating": text_of(block, '[data-hook="review-star-rating"]'), "title": text_of(block, '[data-hook="review-title"]'), "text": text_of(block, '[data-hook="review-body"]'), "date": text_of(block, '[data-hook="review-date"]'), }) except Exception as e: print(f"Skipped a review: {e}") return reviews
Вспомогательная функция text_of запрашивает один элемент внутри одного блока отзыва и возвращает None при его отсутствии, вместо того чтобы выбрасывать исключение при вызове .get_text() на несуществующем объекте. Это делает извлечение устойчивым к отсутствию поля. Селектор звёздного рейтинга предусматривает запасной вариант: если review-star-rating возвращает ничего для конкретного варианта вёрстки, замените его на review-star-rating-view-point, используемый Amazon на некоторых страницах. Рейтинг приходит как строка вида "4.0 out of 5 stars"; разбейте её по " out of" позже, если для модели нужно числовое значение.
Amazon часто пересматривает разметку, и имена утилитарных классов меняются без предупреждения. Именно поэтому приведённые выше селекторы опираются на атрибуты data-hook, которые долговечнее. Если поле возвращает None для каждого отзыва, повторно проверьте живую страницу отзывов в инструментах разработчика браузера и обновите селектор. Периодическое обслуживание, норма для любого производственного парсера, а не признак поломки. Парсер amazon-product-reviews Scraper API существует именно для того, чтобы переложить эту задержку на обслуживание на него.
Шаг 3: Обход пагинации отзывов
Одна страница, это демонстрация; реальная задача охватывает каждую страницу отзывов о товаре. Amazon пагинирует отзывы с помощью параметра запроса pageNumber, поэтому вы обходите страницы, инкрементируя его и останавливаясь, когда страница не возвращает блоков отзывов. Это исключает необходимость жёстко задавать количество страниц и естественно обрабатывает товары с небольшим числом отзывов.
Для понимания паттерна сравните URL, которые использует Amazon:
-
Страница 1
.../product-reviews/B09Z7KGTVW/?reviewerType=all_reviews -
Страница 2
.../product-reviews/B09Z7KGTVW/?reviewerType=all_reviews&pageNumber=2 -
Страница 3
.../product-reviews/B09Z7KGTVW/?reviewerType=all_reviews&pageNumber=3
import time def scrape_all_reviews(base_url, max_pages=10): all_reviews = [] for page in range(1, max_pages + 1): page_url = f"{base_url}&pageNumber={page}" html = crawl(page_url) if not html: break reviews = parse_reviews(html) if not reviews: print(f"No reviews on page {page}; stopping.") break all_reviews.extend(reviews) print(f"Page {page}: {len(reviews)} reviews") time.sleep(2) return all_reviews
Ограничение max_pages удерживает выполнение в рамках, чтобы товар с тысячами отзывов не запускался бесконечно, а прерывание по пустым результатам останавливает цикл досрочно, когда Amazon заканчивает страницы. time.sleep(2) между страницами задаёт темп, чтобы не нагружать сайт в плотном цикле, что является самым быстрым способом попасть под ограничения. Настройте оба значения в соответствии с вашим объёмом и лимитами скорости ниже.
Шаг 4: Собрать и сохранить данные
Теперь свяжите получение данных, разбор и пагинацию в один готовый к запуску скрипт, а затем запишите собранные отзывы в JSON и CSV. JSON сохраняет вложенную структуру для конвейера; CSV напрямую загружается в таблицу или DataFrame pandas для работы с тональностью.
import csv import json import time from crawlbase import CrawlingAPI from bs4 import BeautifulSoup api = CrawlingAPI({"token": "YOUR_CRAWLBASE_TOKEN"}) REVIEWS_URL = ( "https://www.amazon.com/Meta-Quest-Pro-Oculus/product-reviews/" "B09Z7KGTVW/?reviewerType=all_reviews" ) def crawl(page_url): options = {"ajax_wait": "true", "page_wait": 3000} 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 text_of(block, selector): el = block.select_one(selector) return el.get_text(strip=True) if el else None def parse_reviews(html): soup = BeautifulSoup(html, "html.parser") blocks = soup.select('div[data-hook="review"]') reviews = [] for block in blocks: try: reviews.append({ "reviewer_name": text_of(block, "span.a-profile-name"), "rating": text_of(block, '[data-hook="review-star-rating"]'), "title": text_of(block, '[data-hook="review-title"]'), "text": text_of(block, '[data-hook="review-body"]'), "date": text_of(block, '[data-hook="review-date"]'), }) except Exception as e: print(f"Skipped a review: {e}") return reviews def scrape_all_reviews(base_url, max_pages=10): all_reviews = [] for page in range(1, max_pages + 1): page_url = f"{base_url}&pageNumber={page}" html = crawl(page_url) if not html: break reviews = parse_reviews(html) if not reviews: break all_reviews.extend(reviews) print(f"Page {page}: {len(reviews)} reviews") time.sleep(2) return all_reviews def save(reviews): with open("amazon_reviews.json", "w", encoding="utf-8") as f: json.dump(reviews, f, indent=2, ensure_ascii=False) if reviews: with open("amazon_reviews.csv", "w", newline="", encoding="utf-8") as f: writer = csv.DictWriter(f, fieldnames=reviews[0].keys()) writer.writeheader() writer.writerows(reviews) print(f"Saved {len(reviews)} reviews to JSON and CSV") def main(): reviews = scrape_all_reviews(REVIEWS_URL) save(reviews) if __name__ == "__main__": main()
Запустите командой python scraper.py. Скрипт обходит страницы отзывов, выводит счётчик по каждой странице и записывает amazon_reviews.json и amazon_reviews.csv в ту же директорию. Отсюда записи поступают в модель тональности, график динамики рейтинга или сравнение с товаром конкурента. Перед этим стоит пропустить данные через обработку структурирования и очистки спарсенных данных для AI и ML, чтобы рейтинги и даты приобрели согласованные типы.
Как выглядит результат
Каждая запись, это плоский объект с пятью полями. JSON-файл выглядит следующим образом:
[ { "reviewer_name": "Grrgoyl", "rating": "4.0 out of 5 stars", "title": "No regret", "text": "My 256 gb Quest 2 is in danger of running out of space, so the Pro was an easy call.", "date": "Reviewed in the United States on August 2, 2023" }, { "reviewer_name": "Damian", "rating": "3.0 out of 5 stars", "title": "Excellent comfort, poor display", "text": "I purchased this to upgrade from my first gen Rift and the comfort is great, the display less so.", "date": "Reviewed in the United States on November 1, 2022" } ]
CSV содержит те же пять столбцов: reviewer_name, rating, title, text и date. Если хотите полностью пропустить разбор, Crawling API возвращает эти поля в виде предварительно разобранного JSON через парсер amazon-product-reviews, который также предоставляет дополнения, такие как ID отзыва и флаг верифицированной покупки.
Как оставаться незаблокированным
Даже при обработке рендеринга и ротации Amazon отслеживает трафик, характерный для парсеров. Несколько привычек поддерживают работоспособность сессии и применимы к любой хорошо защищённой коммерческой цели.
-
Регулируйте темп запросов. Распределяйте запросы с задержкой между страницами вместо обхода на полной скорости.
time.sleepв цикле пагинации, это минимум, а не максимум. - Полагайтесь на ротацию. Пул резидентских IP распределяет запросы по множеству реальных пользовательских адресов, чтобы ни один не превысил лимит скорости. Crawling API управляет этим за вас; если вы строите свой стек, именно эту часть нужно реализовать правильно.
- Читайте коды статусов. Если сессия начинает возвращать вызовы или ошибки, это сигнал о том, что текущий темп или уровень IP недостаточен. Воспринимайте это как сигнал к снижению активности, а не как шум, который нужно игнорировать.
Более широкий план действий описан в как парсить сайты без блокировок. Если вас интересует полная картина отзывов по нескольким ритейлерам, общее руководство как парсить отзывы покупателей охватывает кроссплатформенные паттерны, а парсинг данных о товарах Amazon хорошо дополняет это руководство, когда нужны данные объявления вместе с отзывами.
Законен ли парсинг отзывов Amazon?
Допустимость парсинга отзывов Amazon зависит от условий использования Amazon, вашей юрисдикции и того, что вы делаете с данными. Условия использования Amazon ограничивают автоматизированный доступ, поэтому парсинг может нарушать эти условия независимо от тщательности вашего инструментария. Ни один из приведённых здесь примеров кода этого не меняет; он просто обеспечивает работу технической части. Ознакомьтесь с условиями использования Amazon и его robots.txt и воспринимайте оба документа как границу того, что вы собираете. Amazon также запускает CAPTCHA-проверки для подтверждения присутствия человека, что является частью той же оборонительной позиции.
Несколько принципов, которых стоит придерживаться. Собирайте только публичный текст отзывов: рейтинг, заголовок, текст и дату, которые любой посетитель может прочитать на странице отзывов без аккаунта. Отображаемое в отзыве имя публично, но это максимум, что вы должны сохранять. Не составляйте профили отдельных рецензентов, не переходите по ссылкам на профили для сбора истории отзывов человека по разным товарам и не пытайтесь связать отображаемое имя с реальной личностью. Уважайте конфиденциальность и воспринимайте каждый отзыв как точку данных о товаре, а не о человеке.
Это руководство намеренно ограничено публичными страницами отзывов, поскольку именно это позволяет работе оставаться защищаемой. Оно не охватывает данные за логином, данные аккаунтов или заказов, а также любые попытки обойти аутентификацию и не перераспределяет охраняемые авторским правом медиаматериалы отзывов. Для лицензированного или массового доступа Amazon предлагает официальные API и партнёрские программы по данным о товарах и отзывах, и это правильный инструмент при необходимости больших объёмов, гарантированной структуры или коммерческих прав. Если вашему проекту нужно больше, чем публичный текст отзывов, официальный API или соглашение на данные, правильный путь, а не более хитрый парсер.
Ключевые выводы
- Обычный запрос блокируется. Amazon встречает голый HTTP-трафик проверкой на робота или CAPTCHA, поэтому нужна отрендеренная страница за доверенным IP, именно это Crawling API даёт в одном вызове.
-
Ориентируйтесь на атрибуты data-hook. Каждый отзыв находится в блоке
div[data-hook="review"], с именем, рейтингом, заголовком, текстом и датой, доступными через стабильные селекторыdata-hook, которые долговечнее имён утилитарных классов. -
Пагинация через pageNumber. Перебирайте
&pageNumber=до тех пор, пока страница не вернёт пустой список отзывов, задавайте темп с задержкой и ограничивайте количество страниц. - Экспортируйте в JSON и CSV. JSON сохраняет структуру для конвейера; CSV загружается в таблицу или pandas для анализа тональности и трендов.
- Оставайтесь в рамках публичного текста отзывов. Соблюдайте условия использования Amazon и robots.txt, ограничивайтесь публичным рейтингом и текстом, никогда не составляйте профили отдельных рецензентов и для лицензированных или массовых данных предпочитайте официальный API.
Часто задаваемые вопросы
Почему обычный запрос не работает на странице отзывов Amazon?
Amazon жёстко защищается от автоматизированного трафика. IP датацентра или запрос, не похожий на настоящий браузер, встречает CAPTCHA, промежуточную страницу Robot Check или блокировку ещё до достижения блоков отзывов, а части страницы вдобавок рендерятся через JavaScript. Crawling API рендерит страницу за доверенным резидентским IP, поэтому отзывы присутствуют при разборе BeautifulSoup.
Какие поля можно извлечь из отзыва Amazon?
Этот парсер извлекает публичное отображаемое имя рецензента, звёздный рейтинг, заголовок отзыва, текст отзыва и дату. Каждое из них сопоставлено с атрибутом data-hook внутри блока отзыва: review-star-rating, review-title, review-body и review-date, плюс span.a-profile-name для имени. Парсер amazon-product-reviews Scraper API возвращает те же поля плюс дополнения, такие как ID отзыва и флаг верифицированной покупки.
Как спарсить все страницы отзывов?
Amazon пагинирует отзывы с помощью параметра запроса pageNumber в URL product-reviews. Инкрементируйте его в цикле, разбирайте каждую страницу тем же кодом и останавливайтесь, когда страница не возвращает блоков отзывов. Ограничьте количество страниц и добавляйте короткую задержку между запросами для задания темпа и предотвращения ограничений.
Мои селекторы возвращают None. Что изменилось?
Скорее всего, разметка Amazon. Имена утилитарных классов меняются без предупреждения, поэтому приведённые выше селекторы опираются на атрибуты data-hook. Если звёздный рейтинг возвращается пустым, попробуйте review-star-rating-view-point, используемый Amazon на некоторых вариантах вёрстки. Повторно проверьте живую страницу отзывов в инструментах разработчика браузера и обновите селектор; периодическое обслуживание, норма для любого производственного парсера.
Можно ли использовать спарсенные отзывы для анализа тональности?
Да, это одна из наиболее распространённых причин их сбора. Экспортируйте в CSV, загрузите в pandas и прогоните текст отзывов через модель тональности или анализ динамики рейтинга. Сначала преобразуйте рейтинг в числовое значение и дату, в правильный тип данных, чтобы поля были готовы к использованию в модели.
Безопасно ли хранить имена рецензентов?
Минимизируйте сбор. Отображаемое имя в публичном отзыве публично, но это максимум, что стоит хранить, и его никогда не следует использовать для построения профиля отдельного рецензента или привязки имени к реальной личности. Воспринимайте каждый отзыв как точку данных о товаре, уважайте конфиденциальность и перед хранением любого персонального поля проверьте условия Amazon и местное законодательство о защите данных.
Обходите любой сайт в масштабе, без борьбы с инфраструктурой.
Crawlbase берёт на себя прокси, отпечатки и CAPTCHA, чтобы ваша команда выпускала конвейеры данных вместо поддержки обвязки краулинга. 1 000 запросов бесплатно, без карты.

