Rotten Tomatoes является одним из наиболее часто упоминаемых источников оценок фильмов в открытом вебе. Страницы фильмов содержат оценку критиков по шкале Tomatometer, зрительскую оценку, жанр и ссылку на полную страницу с названием, причём всё это видно любому пользователю без регистрации. Для исследования в области развлечений, анализа тенденций или создания личной кинобазы данных эти публичные данные об оценках действительно полезно собирать в структурированном виде.
Это руководство показывает, как парсить оценки фильмов Rotten Tomatoes с помощью Python. Весь процесс ограничен публичными, неличными данными: название, оценки, жанр и ссылка на страницу, которые сайт отображает открыто. Мы не затрагиваем идентификаторы рецензентов, полный текст рецензий или что-либо за логином. Поскольку Rotten Tomatoes отображает оценки на клиентской стороне с помощью JavaScript, запросы направляются через Crawling API, чтобы страница была полностью загружена до парсинга.
Что вы создадите
Небольшой Python-парсер, который принимает одну или несколько публичных страниц фильмов Rotten Tomatoes, получает каждую отрисованную страницу через Crawling API, парсит несколько публичных полей и экспортирует результат в JSON и CSV:
- Название фильма имя фильма, отображаемое на странице.
- Оценка Tomatometer оценка критиков, агрегированная от одобренных рецензентов.
- Зрительская оценка совокупная зрительская оценка фильма.
- Жанр категория, к которой относится фильм, например комедия или драма.
- Ссылка канонический URL страницы фильма на Rotten Tomatoes.
Это всё публичные, агрегированные факты о самом фильме. Парсер обрабатывает несколько фильмов за один запуск и формирует чистый датасет, который можно загрузить в ноутбук или таблицу.
Почему обычный запрос не работает на Rotten Tomatoes
Если запросить URL фильма на Rotten Tomatoes через обычный HTTP-клиент, оценок там не будет. Числа Tomatometer и зрительской оценки, а также большая часть метаданных рейтинга загружаются динамически через JavaScript после получения исходного HTML. Библиотека типа requests видит только первичную оболочку разметки, поэтому нужные поля возвращаются пустыми. Кроме того, повторяющийся автоматизированный трафик с одного дата-центрового IP нередко блокируется ещё до отрисовки контента.
Работающий парсер поэтому требует двух вещей в одном запросе: браузера, выполняющего JavaScript страницы, и IP-адреса, который сайт воспринимает как обычного посетителя. Можно собрать это самостоятельно с помощью headless-браузера и пула резидентных прокси, но поддержка такого стека занимает большую часть усилий. Crawling API объединяет оба требования в одном вызове. Вы передаёте ему URL с JavaScript-токеном, он отрисовывает страницу через доверенный резидентный IP и возвращает готовый HTML, который можно сразу передать в BeautifulSoup. Подробнее см. наше руководство о парсинге JavaScript-сайтов.
Crawlbase предлагает два типа токенов. Обычный токен получает статический HTML; JavaScript (JS) токен сначала отрисовывает страницу в реальном браузере. Оценки Rotten Tomatoes встраиваются на клиентской стороне, поэтому здесь нужен JS-токен. Обычный токен возвращает ту же неполную оболочку, что и обычный запрос.
Что нужно подготовить
Несколько вещей, которые нужно иметь под рукой. Ни одна не займёт много времени.
Базовые знания Python. Вы должны уметь запускать скрипт и устанавливать пакеты через pip. Если парсинг HTML для вас в новинку, наш вводный материал о работе с BeautifulSoup в Python охватывает сторону извлечения данных, а руководство парсинг сайта на Python описывает полный цикл.
Python 3.8 или новее. Проверьте командой python --version. Если не установлен, загрузите с python.org.
Аккаунт Crawlbase и JS-токен. Зарегистрируйтесь, откройте панель управления и скопируйте свой JavaScript (JS) токен. Crawlbase даёт до 20 000 бесплатных запросов для старта, и вы платите только за успешные запросы. Храните токен как пароль и не добавляйте его в систему контроля версий.
Настройка проекта
Создайте изолированное виртуальное окружение, затем установите две библиотеки, необходимые парсеру.
python --version python -m venv rt_env source rt_env/bin/activate pip install crawlbase beautifulsoup4
В Windows активируйте через rt_env\Scripts\activate вместо строки с source. Две зависимости выполняют всю работу: crawlbase является официальным клиентом для Crawling API, а beautifulsoup4 парсит возвращённый HTML, позволяя извлекать отдельные поля по селектору.
Шаг 1: Получение отрисованной страницы фильма
Начните с получения готовой страницы. Импортируйте CrawlingAPI, инициализируйте его с вашим JS-токеном и запросите публичный URL фильма. Для цели с клиентской отрисовкой важны два параметра ожидания: ajax_wait говорит API подождать завершения асинхронного контента, а page_wait выдерживает фиксированное количество миллисекунд после загрузки, чтобы оценки появились до захвата страницы. Проверяйте статус перед парсингом, чтобы ошибки были явными, а не молчаливыми.
from crawlbase import CrawlingAPI crawling_api = CrawlingAPI({"token": "YOUR_CRAWLBASE_TOKEN"}) def fetch_html(url): options = {"ajax_wait": "true", "page_wait": "5000"} response = crawling_api.get(url, options) if response["headers"]["cb_status"] == "200": return response["body"].decode("utf-8") print(f"Failed to fetch the page. Status code: {response['headers']['cb_status']}") return None if __name__ == "__main__": url = "https://www.rottentomatoes.com/m/beetlejuice_beetlejuice" html = fetch_html(url) print(html[:500] if html else "No HTML returned")
Пять секунд является разумной отправной точкой для page_wait; увеличьте значение, если оценки возвращаются пустыми. В примере используется публичная страница фильма. Запустите скрипт, и вы должны увидеть реальную разметку страницы с названием, что подтверждает работу отрисовки ещё до написания единого селектора.
Rotten Tomatoes встраивает Tomatometer и зрительские оценки на клиентской стороне, поэтому нужна отрисованная страница за доверенным IP в одном вызове. Crawling API принимает JS-токен, запускает страницу в реальном браузере, ротирует через резидентные IP на стороне сервера и отдаёт готовый HTML, избавляя вас от необходимости запускать флот headless-браузеров и пул прокси. Начните с бесплатного тарифа на любой странице фильма.
Шаг 2: Инспекция страницы и парсинг публичных полей
Перед написанием селекторов откройте страницу фильма в браузере и используйте инструменты разработчика, чтобы найти расположение каждого поля. На странице фильма Rotten Tomatoes структура достаточно стабильна для прямого таргетирования:
-
Название находится в элементе
<h1>с атрибутомslot="titleIntro". -
Оценка Tomatometer (критиков) находится внутри элемента
rt-textсslot="criticsScore". -
Зрительская оценка также находится в элементе
rt-textсslot="audienceScore". -
Жанр отображается в списке деталей фильма, под
<dt>с меткой Genre, а значения находятся в соответствующем<dd>.
Имея готовый HTML, загрузите его в BeautifulSoup и извлеките каждое поле. Вспомогательная функция ниже читает название и обе оценки по их slot-селекторам, затем перебирает список деталей для поиска жанра. Каждый поиск защищён, чтобы отсутствующее поле возвращало пустую строку вместо исключения.
from bs4 import BeautifulSoup def text_or_blank(node): return node.text.strip() if node else "" def find_genre(soup): for dt in soup.select("dt.key rt-text"): if dt.text.strip() == "Genre": dd = dt.find_parent("dt").find_next_sibling("dd") if dd: values = [v.text.strip() for v in dd.find_all(["rt-link", "rt-text"]) if v.text.strip()] return ", ".join(values) return "" def parse_movie(html, url): soup = BeautifulSoup(html, "html.parser") title = text_or_blank(soup.select_one('h1[slot="titleIntro"]')) critics_score = text_or_blank(soup.select_one('rt-text[slot="criticsScore"]')) audience_score = text_or_blank(soup.select_one('rt-text[slot="audienceScore"]')) genre = find_genre(soup) return { "title": title, "tomatometer_score": critics_score, "audience_score": audience_score, "genre": genre, "link": url, }
Обе оценки извлекаются прямо из слотов criticsScore и audienceScore. Жанр берётся из списка деталей, где каждая метка находится в dt.key, а значения в соответствующем dd. Объединение значений rt-link и rt-text обрабатывает фильмы, отмеченные несколькими жанрами, например комедией и фэнтези.
Rotten Tomatoes время от времени меняет разметку. Атрибуты slot, использованные здесь, более стабильны, чем глубоко вложенные имена классов, но если поле возвращается пустым, повторно проверьте живую страницу в инструментах разработчика браузера и обновите селектор. Периодическое обслуживание является нормой для любого производственного парсера.
Шаг 3: Обработка нескольких фильмов и экспорт
Большинство исследований начинается со списка фильмов, а не с одной страницы. Свяжите шаги получения и парсинга в один цикл, перебирающий список URL фильмов, регулируйте запросы и записывайте собранные строки в JSON и CSV. JSON сохраняет структуру для ноутбука; CSV загружается прямо в таблицу. Если планируете использовать это для анализа позже, наше руководство по структурированию и очистке собранных данных для AI и ML охватывает следующий шаг.
import csv import json import time from crawlbase import CrawlingAPI from bs4 import BeautifulSoup crawling_api = CrawlingAPI({"token": "YOUR_CRAWLBASE_TOKEN"}) MOVIE_URLS = [ "https://www.rottentomatoes.com/m/beetlejuice_beetlejuice", "https://www.rottentomatoes.com/m/deadpool_and_wolverine", "https://www.rottentomatoes.com/m/twisters", ] def save_to_json(rows, filename="movies.json"): with open(filename, "w") as f: json.dump(rows, f, indent=4) print(f"Saved {len(rows)} movies to {filename}") def save_to_csv(rows, filename="movies.csv"): fields = ["title", "tomatometer_score", "audience_score", "genre", "link"] with open(filename, "w", newline="") as f: writer = csv.DictWriter(f, fieldnames=fields) writer.writeheader() writer.writerows(rows) print(f"Saved {len(rows)} movies to {filename}") def main(): movies = [] for url in MOVIE_URLS: html = fetch_html(url) if html: movies.append(parse_movie(html, url)) time.sleep(3) save_to_json(movies) save_to_csv(movies) if __name__ == "__main__": main()
Здесь повторно используются вспомогательные функции fetch_html и parse_movie из предыдущих шагов, поэтому вставьте все три блока в один файл. time.sleep(3) между запросами не является украшением: выдержка темпа является главным фактором успешности запуска. Добавьте свои URL фильмов в MOVIE_URLS, и скрипт последовательно соберёт каждый из них.
Как выглядит результат
Запустите полный скрипт и получите чистую запись публичных полей для каждого фильма, готовую к загрузке в ноутбук или таблицу.
[ { "title": "Beetlejuice Beetlejuice", "tomatometer_score": "77%", "audience_score": "81%", "genre": "Comedy, Fantasy", "link": "https://www.rottentomatoes.com/m/beetlejuice_beetlejuice" }, { "title": "Deadpool & Wolverine", "tomatometer_score": "79%", "audience_score": "95%", "genre": "Action, Comedy", "link": "https://www.rottentomatoes.com/m/deadpool_and_wolverine" } ]
Зеркало CSV содержит те же столбцы, по одной строке на фильм, с заголовочной строкой. Отсюда можно сортировать по Tomatometer, сравнивать оценки критиков и зрителей или фильтровать по жанру для любого исследования в области развлечений.
Масштабирование на большее число фильмов и сохранение доступа
Описанный выше паттерн хорошо масштабируется: более длинный список MOVIE_URLS или шаг обнаружения, который сначала собирает ссылки на фильмы с публичной страницы просмотра, например списка кассовых сборов, а затем переходит на каждую страницу с названием. Несколько привычек помогут крупному запуску оставаться стабильным, и они применимы к любой защищённой цели.
- Регулируйте запросы. Сохраняйте задержку между вызовами и не стремитесь к агрессивному параллелизму. Ограничение темпа является лучшим способом получить чистый запуск.
- Используйте ротацию. Crawling API распределяет запросы по резидентным IP за вас, поэтому ни один адрес не превышает лимит частоты. Если создаёте собственный стек, именно эту часть нужно сделать правильно.
- Следите за кодами состояния. Когда запуск начинает возвращать статусы не 200, притормозите, а не давите сильнее.
- Держите объём разумным. Исследование публичных оценок редко требует полного каталога. Выборка нужных фильмов и остановка.
Общие рекомендации см. в нашем руководстве о как парсить сайты без блокировок.
Законно ли парсить Rotten Tomatoes?
Этот раздел стоит прочитать перед написанием производственного кода. Подход здесь ограничен публичными, неличными данными рейтинга: название фильма, оценки Tomatometer и зрителей, жанр и ссылка на страницу. Это агрегированные факты о фильме, а не личные данные об отдельном человеке, что однозначно относит это к образовательной стороне работы с публичными данными. Тем не менее их сбор с соблюдением этических норм означает уважение к Условиям обслуживания Rotten Tomatoes и его robots.txt, а также регулирование запросов, чтобы не создавать нагрузку на сайт.
Есть чёткие границы, которые нельзя пересекать. Не публикуйте повторно защищённые авторским правом материалы: полный текст рецензий отдельных критиков, редакционные тексты, изображения и видео являются защищённым контентом, а агрегирование прозы чьей-либо рецензии или её привязка к именованному критику представляют собой другую деятельность, отличную от записи публичной оценки. Ограничьтесь числами, жанром и ссылкой. Не пытайтесь получить доступ к чему-либо за логином и не собирайте личные данные рецензентов или пользователей. Там, где личные данные всё же задействованы, применяются режимы конфиденциальности, такие как GDPR и CCPA, включая законное основание для сбора и выполнение запросов на удаление.
Если вам нужны более богатые или крупномасштабные данные о фильмах для реального проекта, санкционированный путь предполагает лицензированный источник данных. Данные Rotten Tomatoes доступны через официальные партнёрства и семейство сервисов Fandango, а также существуют лицензированные кинобазы данных для программного доступа. Для любого постоянного или коммерческого использования официальное соглашение даёт гарантированную структуру и сохраняет вас в рамках условий, чего парсер обеспечить не может. Рассматривайте это руководство как техническое упражнение по чтению публичных оценок, а не как разрешение зеркалировать сайт.
Ключевые выводы
- Rotten Tomatoes отрисовывается через JavaScript. Оценки загружаются на клиентской стороне, поэтому обычный запрос возвращает неполную оболочку: страницу нужно отрисовать перед парсингом.
-
Отрисовка и доверенный IP в одном вызове. Crawling API с JS-токеном обеспечивает и то, и другое, а
ajax_waitплюсpage_waitуправляют временем ожидания оценок. -
Используйте стабильные slot-атрибуты. Слоты
titleIntro,criticsScoreиaudienceScore, а также список деталей долговечнее вложенных имён классов. - Экспортируйте в JSON и CSV. JSON сохраняет структуру для анализа; CSV загружается в таблицу, оба с одинаковыми публичными полями на фильм.
- Только публичные оценки. Собирайте названия, оценки, жанр и ссылки; никогда не публикуйте повторно защищённый авторским правом текст рецензий и соблюдайте ToS и robots.txt.
Часто задаваемые вопросы
Почему обычный запрос не возвращает оценки с Rotten Tomatoes?
Потому что Tomatometer и зрительские оценки загружаются на клиентской стороне с помощью JavaScript после получения исходного HTML. Обычный HTTP-запрос с библиотекой типа requests видит только первичную оболочку разметки, поэтому эти поля возвращаются пустыми. Предварительная отрисовка страницы, которую обеспечивает JS-токен Crawling API, делает оценки доступными для парсинга.
Нужен обычный токен или JS-токен?
JS-токен. Обычный токен получает статический HTML, который на Rotten Tomatoes является той же неполной оболочкой, что и при обычном запросе. JS-токен отрисовывает страницу в реальном браузере перед возвратом HTML, поэтому оценки и жанр присутствуют при парсинге через BeautifulSoup.
Какие данные Rotten Tomatoes безопасно парсить?
Публичные, неличные факты о фильме: название, оценка Tomatometer, зрительская оценка, жанр и ссылка на страницу. Избегайте повторной публикации защищённых авторским правом материалов, таких как полный текст рецензий критиков, и не собирайте личные данные рецензентов или пользователей. Ограничьтесь агрегированными рейтингами и соблюдайте условия сайта и robots.txt.
Как парсить оценки для многих фильмов сразу?
Поместите URL фильмов в список и переберите их, вызывая вспомогательные функции получения и парсинга для каждого, с коротким перерывом между запросами. Можно также добавить шаг обнаружения, который сначала собирает ссылки с публичной страницы просмотра, а затем переходит на каждую страницу с названием. Держите объём разумным и записывайте результаты в JSON или CSV по ходу работы.
Что происходит, если Rotten Tomatoes меняет свою вёрстку?
Ваши селекторы могут перестать совпадать, и поля будут возвращаться пустыми. Повторно проверьте живую страницу в инструментах разработчика браузера, найдите новый атрибут или элемент для поля и обновите селектор. Опора на атрибуты slot, а не на глубоко вложенные имена классов, снижает частоту таких ситуаций, но периодическое обслуживание является нормой для любого парсера.
Стоит ли использовать официальный источник вместо парсинга?
Для любого постоянного или коммерческого использования: да. Данные Rotten Tomatoes доступны через официальные партнёрства и семейство сервисов Fandango, а для программного доступа существуют лицензированные кинобазы данных. Официальное соглашение даёт гарантированную структуру и сохраняет вас в рамках условий. Подход к парсингу здесь подходит для лёгкого исследования публичных данных без лицензионного доступа.
Обходите любой сайт в масштабе, без борьбы с инфраструктурой.
Crawlbase берёт на себя прокси, отпечатки и CAPTCHA, чтобы ваша команда выпускала конвейеры данных вместо поддержки обвязки краулинга. 1 000 запросов бесплатно, без карты.
