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

В этом руководстве показано, как парсить розничные данные Farfetch с помощью JavaScript и Node.js, используя cheerio. Вы создадите небольшой рабочий скрапер, который получает страницу листинга Farfetch через Crawling API, парсит бренд, название товара, цену и ссылку для каждого элемента, обрабатывает пагинацию и экспортирует результат в формате JSON и CSV. Всё руководство ограничено публичными данными листингов товаров, а раздел о законности в конце не является шаблонным текстом, поэтому прочитайте его перед тем, как направить скрапер на реальные объёмы данных.

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

Скрипт на Node.js, который принимает публичный URL категории Farfetch, получает отрендеренный HTML через Crawling API и извлекает структурированную запись для каждой карточки товара в листинге. В качестве примера мы используем категорию мужской обуви и извлекаем следующие поля для каждого товара:

  • Brand название люксового бренда на карточке, например "Gucci".
  • Description краткое описание товара, например "Screener leather sneakers".
  • Price цена на карточке, включая символ валюты.
  • Discount метка скидки, если товар по акции, иначе "N/A".
  • Link абсолютный URL страницы конкретного товара на farfetch.com.

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

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

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

Ожидание контента

Поскольку Farfetch загружает сетку на клиенте, вы указываете Crawling API дождаться завершения работы JavaScript перед захватом HTML. Установите ajax_wait: 'true' и page_wait в несколько тысяч миллисекунд, чтобы карточки товаров присутствовали в возвращаемой разметке. Рендеринг использует тип запроса JavaScript, поэтому для этих листингов нужен JS-токен, а не обычный запрос.

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

Перед написанием кода необходимо подготовить несколько вещей. Ни одна из них не займёт много времени.

Базовые знания JavaScript и Node.js. Вы должны уметь писать и запускать Node-скрипты, устанавливать пакеты с помощью npm. Если вы новичок в Node, официальная документация и любой вводный курс выведут вас на нужный уровень. Руководство по созданию веб-скрапера с Node.js, хорошее введение, если хотите подготовиться.

Node.js версии 16 или выше. Проверьте версию командой node --version. Если она не установлена, установите с сайта Node.js или через менеджер версий, например nvm.

Аккаунт Crawlbase и токен. Зарегистрируйтесь, откройте панель управления и скопируйте токен. Бесплатный тариф даёт до 5 000 бесплатных запросов без привязки карты. Farfetch требует рендеринга, поэтому используйте для этих запросов JavaScript-токен. Относитесь к токену как к паролю: он аутентифицирует ваши запросы, поэтому держите его вне системы контроля версий.

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

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

bash
node --version

mkdir farfetch-scraper && cd farfetch-scraper
npm init -y

npm install crawlbase cheerio

Две зависимости выполняют всю работу: crawlbase, официальный Node-клиент для Crawling API, а cheerio парсит возвращённый HTML с API в стиле jQuery, позволяя извлекать отдельные поля по CSS-селектору. Создайте файл farfetch-scraper.js в этой папке и добавьте код из приведённых ниже шагов.

Шаг 1: Получение отрендеренной страницы листинга

Начните с получения готовой страницы. Импортируйте класс CrawlingAPI, инициализируйте его с вашим токеном и запросите URL категории с установленными параметрами ожидания, чтобы карточки были отрендерены до захвата HTML. Проверка кода статуса перед парсингом позволяет обнаруживать сбои явно, а не скрыто.

javascript
const { CrawlingAPI } = require('crawlbase');

const api = new CrawlingAPI({ token: 'YOUR_CRAWLBASE_TOKEN' });

const options = {
  ajax_wait: 'true',    // wait for the JavaScript grid to load
  page_wait: '5000'     // give the page 5 seconds to settle
};

const listingURL =
  'https://www.farfetch.com/shopping/men/shoes-2/items.aspx';

api
  .get(listingURL, options)
  .then((response) => {
    if (response.statusCode === 200) {
      console.log(response.body.slice(0, 500));
    }
  })
  .catch((error) => console.error('API request error:', error));

Запустите скрипт командой node farfetch-scraper.js, в верхней части тела вы должны увидеть реальную разметку товаров Farfetch, а не урезанную оболочку. Это подтверждает, что рендеринг работает ещё до написания первого селектора. Параметры ajax_wait и page_wait дают клиентской сетке время на заполнение; подробнее о доступных параметрах запроса можно прочитать в документации Crawling API.

Crawlbase Crawling API

Первый запрос только что вернул полностью отрендеренный листинг Farfetch без headless-браузера и прокси на вашей стороне. Crawling API запускает страницу в реальном браузере, ожидает загрузки JavaScript-сетки с помощью ajax_wait и page_wait, ротирует резидентские IP на стороне сервера и обрабатывает проверки, которые Farfetch подбрасывает скраперам, так что вы получаете готовый HTML из одного вызова. Попробуйте сначала на категории мужской обуви на бесплатном тарифе.

Шаг 2: Парсинг каждой карточки товара с помощью cheerio

Имея в распоряжении отрендеренный HTML, загрузите его в cheerio и обойдите карточки товаров. Farfetch размещает каждый элемент как list-элемент внутри каталожной сетки, поэтому вы выбираете каждую карточку, а затем считываете бренд, описание, цену, скидку и ссылку из её содержимого. Защитное чтение каждого поля предотвращает сбой всего запуска из-за одного отсутствующего значения.

javascript
const cheerio = require('cheerio');

function parseListings(html) {
  const $ = cheerio.load(html);
  const products = [];

  const cards = $(
    'ul#catalog-grid > li[data-testid="productCard"]'
  );

  cards.each((index, element) => {
    const card = $(element);

    const brand = card
      .find('p[data-component="ProductCardBrandName"]')
      .text()
      .trim() || 'N/A';

    const description = card
      .find('p[data-component="ProductCardDescription"]')
      .text()
      .trim() || 'N/A';

    const price = card
      .find('p[data-component="Price"], p[data-component="PriceFinal"]')
      .first()
      .text()
      .trim() || 'N/A';

    const discount = card
      .find('p[data-component="PriceDiscount"]')
      .text()
      .trim() || 'N/A';

    const href = card.find('a').first().attr('href');
    const link = href
      ? new URL(href, 'https://www.farfetch.com').href
      : 'N/A';

    products.push({ brand, description, price, discount, link });
  });

  return products;
}

Селекторы взяты прямо со страницы. Каждая карточка, это li[data-testid="productCard"] внутри ul#catalog-grid. Бренд находится в p с тегом data-component="ProductCardBrandName", описание в ProductCardDescription, а цена в Price или PriceFinal, поэтому селектор соответствует обоим и берёт первый. При наличии скидки метка скидки находится в PriceDiscount. Ссылка на товар берётся из anchor href карточки, который Farfetch возвращает как относительный путь, и разрешается относительно https://www.farfetch.com для получения абсолютного URL.

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

Атрибуты data-component и data-testid Farfetch, стабильные маркеры, но разметка со временем меняется. Считайте приведённые выше селекторы отправной точкой, а не постоянным контрактом. Когда поле повсеместно возвращается как "N/A", повторно проинспектируйте живую страницу в инструментах разработчика браузера и обновите селектор. Периодическое обслуживание селекторов нормально для любого продакшн-скрапера, а не признак поломки.

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

Farfetch распределяет листинги по множеству страниц. Чтобы собрать полную категорию, обходите страницы, добавляя параметр page к URL и выполняя одно и то же получение данных с парсингом на каждой странице, затем объедините всё в один список.

javascript
async function crawl(pageUrl) {
  const response = await api.get(pageUrl, options);
  if (response.statusCode === 200) return response.body;
  console.error(`Request failed: ${response.statusCode}`);
  return null;
}

async function scrapeMultiplePages(baseUrl, totalPages) {
  const allProducts = [];

  for (let page = 1; page <= totalPages; page++) {
    const paginatedUrl = `${baseUrl}?page=${page}`;
    console.log(`Scraping page: ${page}`);
    const html = await crawl(paginatedUrl);
    if (!html) continue;
    allProducts.push(...parseListings(html));
  }

  return allProducts;
}

Цикл идёт от страницы 1 до totalPages, строя URL каждой страницы как ?page=N, получая её через Crawling API с теми же параметрами ожидания, парсируя карточки и добавляя результаты в один объединённый массив. Поскольку каждая страница категории имеет одинаковую структуру карточек, функция parseListings из шага 2 работает для всех без изменений.

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

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

javascript
const fs = require('fs');
const { CrawlingAPI } = require('crawlbase');
const cheerio = require('cheerio');

const api = new CrawlingAPI({ token: 'YOUR_CRAWLBASE_TOKEN' });

const options = { ajax_wait: 'true', page_wait: '5000' };

async function crawl(pageUrl) {
  const response = await api.get(pageUrl, options);
  if (response.statusCode === 200) return response.body;
  console.error(`Request failed: ${response.statusCode}`);
  return null;
}

function parseListings(html) {
  const $ = cheerio.load(html);
  const products = [];

  $('ul#catalog-grid > li[data-testid="productCard"]').each((i, el) => {
    const card = $(el);
    const brand = card.find('p[data-component="ProductCardBrandName"]').text().trim() || 'N/A';
    const description = card.find('p[data-component="ProductCardDescription"]').text().trim() || 'N/A';
    const price = card.find('p[data-component="Price"], p[data-component="PriceFinal"]').first().text().trim() || 'N/A';
    const discount = card.find('p[data-component="PriceDiscount"]').text().trim() || 'N/A';
    const href = card.find('a').first().attr('href');
    const link = href ? new URL(href, 'https://www.farfetch.com').href : 'N/A';

    products.push({ brand, description, price, discount, link });
  });

  return products;
}

async function scrapeMultiplePages(baseUrl, totalPages) {
  const allProducts = [];
  for (let page = 1; page <= totalPages; page++) {
    console.log(`Scraping page: ${page}`);
    const html = await crawl(`${baseUrl}?page=${page}`);
    if (html) allProducts.push(...parseListings(html));
  }
  return allProducts;
}

function toCsv(rows) {
  const headers = ['brand', 'description', 'price', 'discount', 'link'];
  const escape = (value) => `"${String(value).replace(/"/g, '""')}"`;
  const lines = [headers.join(',')];
  for (const row of rows) {
    lines.push(headers.map((h) => escape(row[h])).join(','));
  }
  return lines.join('\n');
}

async function main() {
  const baseUrl = 'https://www.farfetch.com/shopping/men/shoes-2/items.aspx';
  const products = await scrapeMultiplePages(baseUrl, 5);
  if (!products.length) return;

  fs.writeFileSync('farfetch_listings.json', JSON.stringify(products, null, 2));
  fs.writeFileSync('farfetch_listings.csv', toCsv(products));
  console.log(`Saved ${products.length} products to JSON and CSV`);
}

main();

Запустите командой node farfetch-scraper.js и получите два файла: farfetch_listings.json с полными структурированными записями и farfetch_listings.csv, готовый к открытию в электронной таблице. Вспомогательная функция toCsv заключает каждое поле в кавычки и удваивает встроенные кавычки, что важно, поскольку названия брендов и описания товаров часто содержат запятые.

Как выглядит результат

Файл JSON содержит один объект на карточку товара с брендом, описанием, ценой, скидкой и ссылкой.

json
[
  {
    "brand": "Gucci",
    "description": "Screener leather sneakers",
    "price": "$890",
    "discount": "N/A",
    "link": "https://www.farfetch.com/shopping/men/gucci-screener-sneakers-item-27582236.aspx"
  },
  {
    "brand": "Common Projects",
    "description": "Original Achilles low-top sneakers",
    "price": "$425",
    "discount": "30% off",
    "link": "https://www.farfetch.com/shopping/men/common-projects-original-achilles-item-12345678.aspx"
  }
]

CSV отражает те же строки с заголовочной строкой, поэтому его можно сразу открыть в Excel, Google Sheets или любом конвейере данных, читающем файлы с разделителями.

csv
brand,description,price,discount,link
"Gucci","Screener leather sneakers","$890","N/A","https://www.farfetch.com/shopping/men/gucci-screener-sneakers-item-27582236.aspx"
"Common Projects","Original Achilles low-top sneakers","$425","30% off","https://www.farfetch.com/shopping/men/common-projects-original-achilles-item-12345678.aspx"

Масштабирование на несколько категорий

Одна категория, это демо; реальная задача охватывает несколько отделов Farfetch. Каждая категория живёт по своему пути листинга, например мужская обувь, женские сумки или детская одежда, поэтому можно составить список URL категорий, запустить scrapeMultiplePages для каждой и добавить метку категории в каждую строку перед экспортом. Поскольку каждая страница листинга имеет одинаковую структуру карточек, уже написанный парсер работает для всех без изменений.

Этот паттерн напрямую применим к исследованиям цен и продуктов. Для более широкого понимания извлечения структурированных данных из интернет-магазинов см. руководство по веб-скрапингу в e-commerce, а для превращения этих цен в решения, статью как использовать веб-скрапинг для ценовой аналитики. Если вам нужен тот же подход для другого модного ритейлера, разбор создания скрапера Zalando охватывает аналогичный каталог с тяжёлым JavaScript.

Как не попасть под блокировку

Даже при решённом вопросе рендеринга Farfetch следит за трафиком, похожим на скрапинг. Несколько привычек помогут сохранить работоспособность запуска, и они применимы к любой серьёзной коммерческой цели.

  • Регулируйте частоту запросов. Вводите задержку между получением страниц вместо того, чтобы долбить каталог в плотном цикле. Распределение запросов во времени, главный фактор, позволяющий оставаться в пределах лимитов сайта.
  • Используйте ротацию. Пул резидентских IP распределяет запросы по множеству адресов реальных пользователей, чтобы ни один не превысил лимит или не получил проверку. Crawling API делает это за вас; если вы строите собственный стек, это та часть, которую нужно реализовать правильно.
  • Читайте коды статусов. Запуск, начавший возвращать проверки или не-200 ответы, сигнализирует, что текущая скорость или IP-уровень больше недостаточны. Воспринимайте это как сигнал к снижению активности, а не как шум, который можно игнорировать.

Для общей методики по этому вопросу см. руководство как парсить сайты, не попадая под блокировку, а для понимания механики того, почему эти каталоги вообще требуют реального браузера, статья как краулить JavaScript-сайты разбирает это подробнее.

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

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

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

Для объёмного или коммерческого использования правильный шаг, поискать санкционированный канал. Farfetch работает с партнёрскими и аффилиатными программами через отношения с бутиками и брендами, и именно они являются правильным путём, когда вам нужны большие объёмы, гарантированная структура или коммерческие права. Данное руководство намеренно ограничено публичными данными листингов, поскольку именно эта граница делает работу защищаемой. Оно не охватывает ничего, что скрыто за авторизацией, личных или платёжных данных клиентов и бутиков, истории заказов или любых попыток обойти аутентификацию или проверку, которую вы не должны были проходить. Если вашему проекту нужно больше, чем публичные листинги, официальное партнёрство или соглашение о данных, правильный путь, а не более умный скрапер.

Итоги

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

  • Farfetch рендерит листинги на клиенте и жёстко блокирует. Обычный запрос возвращает пустую оболочку, поэтому необходимо рендерить страницу за доверенным IP с установленными ajax_wait и page_wait прежде, чем парсить её.
  • Crawling API делает всё в одном вызове. Он рендерит страницу, ожидает JavaScript-сетку, ротирует резидентские IP и обрабатывает проверки, возвращая готовый HTML для парсинга с помощью cheerio.
  • cheerio извлекает поля. Выберите каждый li[data-testid="productCard"], затем считайте бренд, описание, цену, скидку и абсолютную ссылку на товар из каждой карточки.
  • Пагинируйте и экспортируйте. Обходите страницы с ?page=N, собирайте записи и записывайте их в JSON и CSV, заключая поля CSV в кавычки, чтобы бренды и описания с запятыми не ломали столбцы.
  • Оставайтесь на публичных данных. Соблюдайте условия и robots.txt Farfetch, регулируйте частоту запросов и предпочитайте официальное партнёрство или аффилиатный канал для объёмного или коммерческого использования.

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

Как работать с JavaScript-контентом при парсинге Farfetch?

Farfetch загружает сетку товаров на клиенте, поэтому сырой HTML почти пуст до запуска скриптов страницы. Направьте запрос через Crawling API с ajax_wait: 'true' и page_wait в несколько тысяч миллисекунд, это даёт JavaScript время на рендеринг до захвата HTML. Используйте JavaScript-токен для этих запросов, поскольку рендеринг, это тип JS-запроса.

Можно ли парсить детали товаров с нескольких страниц Farfetch?

Да. Farfetch пагинирует категории, поэтому добавьте параметр page к URL листинга, например ?page=2, и обойдите нужные страницы в цикле. Выполняйте одно и то же получение данных с парсингом на каждой странице и объединяйте результаты в один массив, как делает функция scrapeMultiplePages в данном руководстве. Маршрутизация каждой страницы через Crawling API обеспечивает единообразие ротации и обработки проверок на протяжении всего запуска.

Какие поля извлекает этот скрапер?

Для каждой карточки товара он извлекает бренд из ProductCardBrandName, описание из ProductCardDescription, цену из Price или PriceFinal, метку скидки из PriceDiscount и ссылку на товар из anchor карточки, разрешённую в абсолютный URL farfetch.com. Отсутствующие значения заменяются на "N/A", чтобы неполная карточка никогда не прерывала запуск.

Мои селекторы возвращают "N/A" для каждой карточки. Что изменилось?

Почти наверняка разметка Farfetch. Маркеры data-component и data-testid достаточно стабильны, но могут меняться, и при обновлении макета поле может перемещаться. Повторно проинспектируйте живую страницу категории в инструментах разработчика браузера и обновите селекторы. Периодическое обслуживание селекторов нормально для любого продакшн-скрапера.

Как хранить спарсенные данные?

Сохраняйте в структурированном формате, таком как JSON или CSV. Данное руководство записывает оба: farfetch_listings.json для дальнейшей обработки и farfetch_listings.csv для электронных таблиц и BI-инструментов. CSV-писатель заключает каждое поле в кавычки и экранирует встроенные кавычки, чтобы запятые внутри брендов или описаний не смещали столбцы.

Можно ли парсить персональные данные с Farfetch?

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

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

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

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

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