Apple App Store, один из крупнейших публичных каталогов программного обеспечения в открытом вебе. На странице каждого приложения есть последовательный блок структурированных данных: название приложения, его разработчик, категория, публичный звёздный рейтинг и количество оценок, цена и канонический URL. Разработчики отслеживают эти данные для бенчмаркинга конкурентов, аналитики изучают тенденции в категориях, а продуктовые команды следят за изменением рейтингов. Всё это находится на публичной странице продукта с предсказуемой структурой, которую может открыть любой без регистрации.
В этом руководстве показано, как краулить данные Apple App Store с помощью JavaScript и Node.js, используя Cheerio. Вы создаёте небольшой запускаемый скрапер, который получает публичную страницу приложения через Crawling API, парсит публичные поля метаданных и экспортирует результат в JSON. Весь разбор ограничивается публичными метаданными приложений. Здесь не собираются и не профилируются отдельные рецензенты, а раздел о законности в конце, не формальность, поэтому прочитайте его, прежде чем направлять скрапер на реальный объём данных.
Что вы создадите
Скрипт Node.js, который принимает публичный URL продукта из App Store, получает готовый HTML через Crawling API и извлекает структурированную запись с публичными метаданными приложения. В качестве рабочего примера используется Google Authenticator, и извлекаются следующие поля:
- Название приложения, заголовок продукта, показанный в верхней части страницы.
- Разработчик, имя продавца или студии, публикующей приложение.
- Категория, категория App Store, под которой указано приложение, например «Utilities».
- Рейтинг, публичный средний звёздный рейтинг, отображаемый Apple для приложения.
- Количество оценок, публичное количество оценок, стоящих за этим средним значением.
- Цена, указанная цена или «Free», когда у приложения нет предоплаты.
- URL приложения, канонический публичный URL страницы продукта.
Почему обычный запрос не работает в App Store
Если вы запрашиваете URL продукта App Store с помощью простого HTTP-клиента, вы редко получаете пригодную разметку. Против вас работают два фактора. Во-первых, Apple рендерит большую часть страницы продукта в браузере, поэтому исходный HTML, это тонкая оболочка до тех пор, пока скрипты страницы не запустятся и не заполнят блоки заголовка, рейтингов и метаданных. Во-вторых, App Store помечает автоматизированный трафик: IP дата-центров и паттерны запросов, не похожие на настоящий браузер, throttle-ятся или блокируются до того, как достигают отрендеренного контента.
Таким образом, работающему скраперу App Store нужны в одном запросе две вещи: браузер, действительно рендерящий страницу, и IP, который платформа воспринимает как реального посетителя. Вы можете собрать это самостоятельно из безголового браузера плюс пул ротирующих жилых прокси, но соединение их вместе и поддержание в рабочем состоянии, это бо́льшая часть работы. Crawling API объединяет оба компонента в одном вызове: вы отправляете ему URL, он рендерит страницу за доверенным IP и возвращает готовый HTML для парсинга с помощью Cheerio.
Crawling API выдаёт вам два токена: обычный и JavaScript. Страницы продуктов App Store требуют рендеринга контента в настоящем браузере, поэтому используйте свой JavaScript-токен для каждого запроса в этом руководстве. Обычный токен возвращает нерендеренную оболочку, и ваши селекторы будут возвращать пустые значения.
Предварительные требования
Прежде чем писать код, нужно подготовить несколько вещей. Ни одна из них не займёт много времени.
Базовые знания JavaScript и Node.js. Вы должны уметь писать и запускать Node-скрипты и устанавливать пакеты с помощью npm. Если вы новичок в Node, официальная документация и любой вводный курс доведут вас до уровня, который предполагает этот учебник. Для более полного разбора наш материал о создании веб-скрапера с Node.js охватывает основы.
Node.js 16 или выше. Проверьте версию командой node --version. Если её нет, установите с сайта Node.js или через менеджер версий, например nvm.
Аккаунт Crawlbase и токен. Зарегистрируйтесь, откройте панель управления и скопируйте JavaScript-токен со страницы документации аккаунта. Бесплатный тариф даёт 1000 запросов без карты, и вы платите только за успешные запросы. Обращайтесь с токеном как с паролем: он аутентифицирует ваши запросы, поэтому не храните его в системе контроля версий.
Настройка проекта
Создайте папку проекта, инициализируйте её и установите две библиотеки, необходимые скраперу.
node --version mkdir appstore-scraper && cd appstore-scraper npm init -y npm install crawlbase cheerio
Две зависимости делают всю работу: crawlbase, официальный Node-клиент для Crawling API, а cheerio парсит возвращаемый HTML с jQuery-подобным API, чтобы вы могли извлекать отдельные поля по CSS-селектору. Создайте файл с именем scraper.js в этой папке и добавьте код из шагов ниже.
Шаг 1: Получение готовой страницы приложения
Начните с получения готовой страницы. Импортируйте класс CrawlingAPI, инициализируйте его с помощью JavaScript-токена и запросите публичный URL продукта App Store. Проверка кода статуса перед парсингом делает сбои громкими, а не тихими.
const { CrawlingAPI } = require('crawlbase'); const api = new CrawlingAPI({ token: 'YOUR_CRAWLBASE_TOKEN' }); const appURL = 'https://apps.apple.com/us/app/google-authenticator/id388497605'; api .get(appURL) .then((response) => { if (response.statusCode === 200) { console.log(response.body.slice(0, 500)); } }) .catch((error) => console.error('API request error:', error));
Запустите скрипт командой node scraper.js, и вы должны увидеть настоящую разметку продукта App Store в верхней части тела ответа, а не урезанную оболочку. Это подтверждает, что рендеринг работает, прежде чем вы напишете хотя бы один селектор. Crawling API использует JavaScript-токен, который вы указали, для рендеринга страницы в настоящем браузере, поэтому блоки заголовка, рейтингов и метаданных присутствуют в полученном HTML.
Этот первый запрос только что вернул полностью отрендеренную страницу продукта App Store без безголового браузера или прокси с вашей стороны. Crawling API запускает страницу в настоящем браузере, ротирует жилые IP на стороне сервера и обрабатывает блокировки, которые App Store бросает в скраперы, поэтому вы получаете готовый HTML из одного вызова. Сначала укажите на публичную страницу приложения на бесплатном тарифе, затем добавьте парсер.
Шаг 2: Парсинг публичных метаданных с помощью Cheerio
Имея готовый HTML, загрузите его в Cheerio и считайте поля из заголовка и блока рейтингов. В заголовке продукта содержатся название приложения, разработчик, категория и цена; виджет рейтингов содержит средний звёздный рейтинг и количество оценок. Защитное считывание каждого поля не даёт одному отсутствующему значению обрушить весь запуск.
const cheerio = require('cheerio'); function parseAppMetadata(html, sourceUrl) { const $ = cheerio.load(html); // App name lives in the product header title let name = $('.app-header__title').text().trim(); const titleBadge = $('.badge--product-title').text().trim(); if (titleBadge) name = name.replace(titleBadge, '').trim(); // Developer / seller const developer = $('.app-header__identity').text().trim(); // Category, parsed from the "... in <Category>" header item let category = null; try { category = $('.product-header__list__item a.inline-list__item') .text() .trim() .split('in')[1] .trim(); } catch { category = null; } // Price, or "Free" when there is no upfront cost const price = $('.app-header__list__item--price').text().trim(); // Public average rating from the star widget's aria-label const rating = $('.we-star-rating').attr('aria-label') || null; // Public rating count, after the "•" separator let ratingCount = null; try { ratingCount = $('.we-rating-count') .text() .trim() .split('•')[1] .trim(); } catch { ratingCount = null; } return { name, developer, category, rating, ratingCount, price, appUrl: sourceUrl, }; }
Несколько деталей делают этот код точным. Название приложения берётся из .app-header__title с отделённым значком product-title, чтобы оставить только само название. Разработчик считывается из .app-header__identity, а категория парсится из текста .product-header__list__item a.inline-list__item, который читается как «Utilities» после слова «in». Цена берётся из .app-header__list__item--price. Для блока рейтингов среднее значение считывается из атрибута aria-label виджета .we-star-rating, а публичное количество оценок берётся из .we-rating-count после разделителя. Каждое поле считывается защитно, поэтому отсутствующий рейтинг или цена возвращает null, а не выбрасывает исключение.
Имена классов Apple (селекторы app-header__* и we-rating-* выше) являются частью разметки, которая меняется со временем. Относитесь к селекторам как к начальному шаблону, а не к контракту. Когда поле возвращается пустым, заново проверьте живую страницу в инструментах разработчика браузера и обновите селектор. Периодическое обслуживание селекторов, норма для любого производственного скрапера, а не признак того, что что-то сломалось.
Шаг 3: Сборка полного скрипта с экспортом в JSON
Теперь объедините получение и парсинг в один запускаемый скрипт, а затем запишите запись на диск в формате JSON. Простой скрипт минимизирует количество движущихся частей; позже вы можете обернуть его в конечную точку, если захотите.
const fs = require('fs'); const { CrawlingAPI } = require('crawlbase'); const cheerio = require('cheerio'); const api = new CrawlingAPI({ token: 'YOUR_CRAWLBASE_TOKEN' }); async function crawl(appUrl) { const response = await api.get(appUrl); if (response.statusCode === 200) return response.body; console.error(`Request failed: ${response.statusCode}`); return null; } async function main() { const appUrl = 'https://apps.apple.com/us/app/google-authenticator/id388497605'; const html = await crawl(appUrl); if (!html) return; const app = parseAppMetadata(html, appUrl); fs.writeFileSync('app.json', JSON.stringify(app, null, 2)); console.log(`Saved metadata for ${app.name}`); } main();
Вставьте функцию parseAppMetadata из шага 2 в тот же файл, чтобы main мог её вызвать. Запустите командой node scraper.js, и вы получите файл app.json с полной структурированной записью. Вспомогательная функция crawl проверяет код статуса и возвращает null при неудачном запросе, поэтому main корректно останавливается, а не парсит сломанную страницу.
Как выглядит вывод
JSON-файл содержит один объект с публичными метаданными приложения: его название, разработчик, категория, средний рейтинг, количество оценок, цена и канонический URL.
{ "name": "Google Authenticator", "developer": "Google LLC", "category": "Utilities", "rating": "4.7 out of 5", "ratingCount": "1.2M Ratings", "price": "Free", "appUrl": "https://apps.apple.com/us/app/google-authenticator/id388497605" }
Эта единственная запись является прочной основой для дальнейшего анализа, отчётности или визуализации. Если хранить такие записи с течением времени, можно отслеживать, как меняются рейтинг и количество оценок приложения, что зачастую и является смыслом всего упражнения.
Масштабирование на множество приложений
Одна страница приложения, это демонстрация; реальная задача предполагает список приложений. App Store не предоставляет единый публичный индекс всех приложений, поэтому вы составляете собственный список URL продуктов, затем проходите по нему, получаете каждое через Crawling API, парсите с помощью той же функции и собираете записи. Поскольку каждая страница продукта имеет одинаковую структуру заголовка и блока рейтингов, уже написанный парсер работает со всеми ними без изменений.
async function scrapeMany(appUrls) { const records = []; for (const url of appUrls) { const html = await crawl(url); if (!html) continue; records.push(parseAppMetadata(html, url)); console.log(`Parsed ${url}`); // Pace requests so you stay under the rate limit await new Promise((r) => setTimeout(r, 2000)); } return records; }
Важные привычки переносятся на любую цель: сначала соберите чистый список URL, парсите каждый с помощью той же функции и добавляйте короткую задержку между запросами, чтобы не перегружать сайт. Подробнее об отрендеренных JavaScript-интенсивных страницах, подобных этой, смотрите в нашем материале о краулинге JavaScript-сайтов.
Как не быть заблокированным
Даже при наличии рендеринга App Store следит за трафиком, похожим на скрапер. Несколько привычек помогают поддерживать работоспособность запуска и применимы к любой сложной коммерческой цели.
- Регулируйте запросы. Добавьте задержку между получением страниц, а не делайте запросы в плотном цикле. Распределение запросов, единственный наиболее важный фактор в соблюдении ограничений частоты.
- Используйте ротацию. Пул жилых IP распределяет запросы по множеству реальных пользовательских адресов, чтобы ни один из них не превысил ограничение или не был заблокирован. Crawling API обрабатывает это за вас; если вы создаёте собственный стек, именно это нужно сделать правильно.
- Читайте коды статуса. Запуск, начинающий возвращать не 200-е ответы, сигнализирует о том, что текущая частота или уровень IP больше не достаточны. Воспринимайте это как сигнал для снижения нагрузки, а не как шум для игнорирования.
Полный плейбук смотрите в материале о как скрапить сайты без блокировок. Если вы хотите готовый инструмент для этой конкретной цели, наш материал о скрапере Apple App Store охватывает ту же тему под другим углом.
Законно ли скрапить Apple App Store?
Разрешено ли скрапить App Store, зависит от условий Apple, вашей юрисдикции и того, что вы делаете с данными. Условия использования Apple ограничивают автоматизированный доступ, поэтому скрапинг может противоречить этим условиям независимо от тщательности вашего инструментария. Ни один из кодов здесь не меняет этого; он просто делает работающей техническую часть. Ознакомьтесь с условиями Apple и файлом robots.txt App Store, соблюдайте заявленные ограничения частоты, придерживайтесь разумного объёма запросов и воспринимайте и то, и другое как границу для того, что вы собираете.
Это руководство намеренно ограничено публичными метаданными приложений: название, разработчик, категория, публичный средний рейтинг, публичное количество оценок, цена и канонический URL, которые любой может увидеть на странице продукта без регистрации. Это отличается от персональных данных на платформе. Отдельные отзывы и люди, которые их написали, являются персональными данными. Используйте количество оценок и средние значения как агрегированный сигнал о приложении, никогда не составляйте профили отдельных рецензентов и не публикуйте отзыв человека, связанный с его личностью. Всё, что находится за аккаунтом Apple, собирается в масштабе или связано с идентифицируемыми лицами, подпадает под действие законов о конфиденциальности, таких как GDPR и CCPA, и это явно выходит за рамки данного материала. Относитесь к защищённым авторскими правами скриншотам, иконкам и тексту описания как к собственности Apple и разработчика, а не к чему-то, что вы можете распространять.
Если вашему проекту нужно больше, чем публичные метаданные, правильный путь, официальный, а не более хитрый скрапер. У Apple есть официальные программы для этих данных. App Store Connect предоставляет вам как разработчику доступ к данным вашего собственного приложения, а публичный iTunes Search API возвращает структурированные метаданные приложений, включая название, разработчика, категорию, цену и рейтинги, по задокументированным условиям. Эти официальные API являются правильными инструментами, когда вам нужны большие объёмы, гарантированная структура или право на коммерческое использование данных. В случае сомнений в допустимости использования получайте разрешение или используйте официальный API, а не предполагайте, что молчание означает согласие.
Ключевые выводы
- App Store рендерит контент на стороне клиента и блокирует автоматизированный трафик. Простой запрос возвращает тонкую оболочку или блокировку, поэтому необходимо рендерить страницу за доверенным IP с использованием JavaScript-токена перед парсингом.
- Crawling API делает оба действия в одном вызове. Он рендерит страницу в настоящем браузере, ротирует жилые IP и обрабатывает блокировки, возвращая готовый HTML для парсинга с помощью Cheerio.
- Cheerio извлекает публичные поля. Считывайте название приложения, разработчика, категорию, рейтинг, количество оценок, цену и URL приложения из заголовка и блоков рейтингов, ожидая со временем изменения имён классов.
- Масштабирование через цикл по списку URL. Составьте собственный список URL продуктов, парсите каждый с помощью той же функции, регулируйте запросы и записывайте структурированные записи в JSON.
- Оставайтесь на публичных метаданных. Собирайте только публичные метаданные приложений, относитесь к отдельным отзывам и рецензентам как к персональным данным, соблюдайте условия Apple и robots.txt, и предпочитайте App Store Connect и iTunes Search API Apple для больших объёмов или коммерческого использования.
Часто задаваемые вопросы
Могу ли я скрапить любое приложение из App Store?
Вы можете получить публичную страницу продукта любого приложения, имея его URL. Apple не публикует полный публичный индекс всех приложений, поэтому вы составляете собственный список URL продуктов из результатов поиска, чартов или уже имеющихся ссылок, а затем проходите по этому списку. Придерживайтесь разумного объёма и оставайтесь на публичных полях метаданных, описанных здесь.
Почему простой запрос возвращает неполные данные из App Store?
Потому что Apple рендерит большую часть страницы продукта в браузере и ограничивает автоматизированный трафик. Обычный HTTP-запрос с IP дата-центра, как правило, возвращает тонкую оболочку, а не контент заголовка и рейтингов. Чтобы получить полную страницу, нужно рендерить её за доверенным IP, с чем Crawling API справляется за вас при использовании JavaScript-токена.
Мои селекторы возвращают пустые значения. Что изменилось?
Почти наверняка разметка Apple. Имена классов, такие как app-header__title и we-rating-count, являются частью разметки, которая меняется со временем, поэтому селекторы, работавшие в прошлом месяце, могут сломаться. Заново проверьте живую страницу в инструментах разработчика браузера, обновите селекторы в parseAppMetadata, и всё снова заработает. Периодическое обслуживание селекторов, норма для любого производственного скрапера.
Могу ли я скрапить отдельные отзывы App Store и имена рецензентов?
Это выходит за рамки данного руководства, и тому есть веская причина. Отдельные отзывы и люди, которые их написали, являются персональными данными, что подпадает под действие законов о конфиденциальности, таких как GDPR и CCPA. Используйте публичное количество оценок и средние значения как агрегированный сигнал о приложении, не составляйте профили отдельных рецензентов и не публикуйте отзыв человека, связанный с его личностью. Для всего, что выходит за пределы публичных метаданных, используйте официальные API Apple.
Есть ли у Apple официальный API для данных о приложениях?
Да. App Store Connect предоставляет разработчикам доступ к данным их собственных приложений, а публичный iTunes Search API возвращает структурированные метаданные приложений, включая название, разработчика, категорию, цену и рейтинги, по задокументированным условиям. Если вам нужны большие объёмы, гарантированная структура или право на коммерческое использование данных, эти официальные пути являются правильным выбором. Этот скрапер публичных метаданных лучше всего подходит для исследований, прототипирования и анализа меньшего масштаба, где официальное соглашение не требуется.
Могу ли я создать скрапер App Store на языке, отличном от JavaScript?
Да. Это руководство использует JavaScript с Cheerio, но тот же подход работает на любом языке. Crawling API имеет библиотеки и SDK для нескольких языков, поэтому вы получаете готовый HTML тем же способом и парсите его с помощью любого HTML-парсера, предпочитаемого вашим стеком, например BeautifulSoup в Python. Селекторы и поля остаются теми же; меняется только синтаксис парсинга.
Обходите любой сайт в масштабе, без борьбы с инфраструктурой.
Crawlbase берёт на себя прокси, отпечатки и CAPTCHA, чтобы ваша команда выпускала конвейеры данных вместо поддержки обвязки краулинга. 1 000 запросов бесплатно, без карты.

