Bloomberg, одна из самых влиятельных платформ финансовых новостей и рынков в открытом вебе. Её разделы и тематические страницы публикуют непрерывный поток заголовков о технологиях, рынках, экономике и политике, каждый с ссылкой, временем публикации и разделом, к которому он относится. Аналитики отслеживают, что движет рынком, исследователи картируют тенденции освещения событий во времени, а продуктовые команды следят за тем, какие истории появляются на каких площадках. Весь этот сигнал содержится в публичном макете листинга раздела страницы ещё до того, как вы откроете какую-либо статью.

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

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

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

  • Headline заголовок статьи, показанный на карточке листинга.
  • Link URL к отдельной статье на bloomberg.com.
  • Published временная метка публикации из элемента time карточки в формате ISO-даты.
  • Section раздел или тема, под которыми подана история, например "Technology".

Обратите внимание на то, чего намеренно нет: текста статьи, аннотации и медиафайлов. Этот скрапер собирает только ссылки и метаданные, но никогда не копирует защищённый авторским правом текст за каждым заголовком.

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

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

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

Используйте JavaScript-токен

Crawling API предоставляет два токена: обычный и JavaScript. Bloomberg требует отрисовки страницы в реальном браузере, поэтому используйте JavaScript-токен для каждого запроса в этом руководстве. Обычный токен возвращает неотрисованную оболочку, и ваши селекторы вернутся пустыми.

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

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

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

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

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

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

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

bash
node --version

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

npm install crawlbase cheerio

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

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

Начните с получения готовой страницы. Импортируйте класс CrawlingAPI, инициализируйте его с помощью JavaScript-токена и запросите публичный URL раздела Bloomberg. В прежнем учебнике использовался раздел технологий, поэтому мы делаем то же самое. Проверка кода статуса перед разбором делает сбои явными, а не скрытыми.

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

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

const bloombergPageURL = 'https://www.bloomberg.com/technology';

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

Запустите скрипт командой node scraper.js и вы должны увидеть реальную разметку раздела Bloomberg в начале тела, а не упрощённую оболочку. Это подтверждает, что отрисовка работает, прежде чем вы напишете хотя бы один селектор. Crawling API использует предоставленный JavaScript-токен для отрисовки страницы в реальном браузере, поэтому карточки историй присутствуют в возвращаемом HTML.

Crawlbase Bloomberg Scraper

Этот первый запрос только что вернул полностью отрисованную страницу раздела технологий Bloomberg без headless-браузера или прокси на вашей стороне. Crawling API запускает страницу в реальном браузере, ротирует резидентные IP на стороне сервера и обрабатывает проверки, которые Bloomberg бросает скраперам, так что вы получаете готовый HTML из одного вызова. Сначала направьте его на публичную страницу раздела на бесплатном уровне, затем добавьте парсер.

Шаг 2: Разбор каждого заголовка с помощью Cheerio

Получив отрисованный HTML, загрузите его в Cheerio и пройдите по ссылкам историй. На странице раздела Bloomberg каждая статья доступна через якорь, href которого указывает на путь /news/articles/, а заголовок раздела находится в элементе eyebrow над листингом. В прежнем учебнике раздел читался из .Eyebrow_sectionTitle-Wew2fboZsjA- a, а дата публикации, из элемента time страницы через атрибут datetime; мы повторно используем эти подходы и собираем одну запись на каждую ссылку истории. Защитное чтение каждого поля не позволяет одному отсутствующему значению нарушить весь запуск.

javascript
const cheerio = require('cheerio');

function parseDataFromHTML(html) {
  const $ = cheerio.load(html);
  const seen = new Set();
  const results = {
    section: '',
    articles: [],
  };

  // Section / topic title from the eyebrow element
  results.section =
    $('.Eyebrow_sectionTitle-Wew2fboZsjA- a').first().text().trim() ||
    'Technology';

  // One record per public article link on the listing
  $('a[href*="/news/articles/"]').each((_, element) => {
    const anchor = $(element);
    const headline = anchor.text().replace(/\n\s+/g, ' ').trim();
    let link = anchor.attr('href');
    if (!headline || !link) return;

    if (link.startsWith('/')) {
      link = new URL(link, 'https://www.bloomberg.com').href;
    }
    if (seen.has(link)) return; // skip duplicate links
    seen.add(link);

    // Published timestamp from a nearby time element, if present
    const timeAttr = anchor
      .closest('article')
      .find('time')
      .attr('datetime');
    const published = timeAttr ? timeAttr.split('T')[0] : '';

    results.articles.push({
      headline,
      link,
      published: published || 'Date not available',
      section: results.section,
    });
  });

  return results;
}

Несколько деталей обеспечивают точность относительно страницы. Заголовок раздела берётся из якоря .Eyebrow_sectionTitle-Wew2fboZsjA-, точно так же, как читал его прежний парсер. Каждая история сопоставляется с якорем, указывающим на /news/articles/, и мы преобразуем относительные пути в абсолютные URL bloomberg.com, чтобы ссылка работала вне страницы. Set удаляет дублирующиеся ссылки, поскольку одна и та же статья часто появляется в нескольких модулях на странице раздела. Дата публикации читается из атрибута datetime ближайшего элемента time и обрезается до ISO-даты с помощью split('T')[0], тот же подход, который оригинал использовал для временной метки статьи.

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

Сгенерированные имена классов Bloomberg (суффикс Eyebrow_* выше) меняются без предупреждения, а страницы разделов часто перестраивают свои модули. Рассматривайте селекторы как отправную точку, а не контракт. Когда заголовок или раздел возвращается пустым, повторно проверьте живую страницу в инструментах разработчика браузера и обновите селектор. Периодическое обслуживание селекторов, норма для любого продакшн-скрапера, а не признак поломки.

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

Теперь соедините получение и разбор в один работоспособный скрипт, затем запишите записи на диск в форматах JSON и CSV. В прежнем руководстве необработанный HTML сохранялся в файл и разбирался во втором проходе; один скрипт сокращает количество движущихся частей и выполняет ту же работу от начала до конца.

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

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

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

function toCsv(rows) {
  const headers = ['headline', 'link', 'published', 'section'];
  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 url = 'https://www.bloomberg.com/technology';
  const html = await crawl(url);
  if (!html) return;

  const data = parseDataFromHTML(html);
  fs.writeFileSync('bloomberg.json', JSON.stringify(data, null, 2));
  fs.writeFileSync('bloomberg.csv', toCsv(data.articles));
  console.log(`Saved ${data.articles.length} headlines to JSON and CSV`);
}

main();

Вставьте функцию parseDataFromHTML из шага 2 в тот же файл, чтобы main могла её вызвать. Запустите скрипт командой node scraper.js и вы получите два файла: bloomberg.json с полными структурированными записями и bloomberg.csv, готовый к открытию в таблице. Вспомогательная функция toCsv заключает каждое поле в кавычки и удваивает все встроенные кавычки, что важно здесь, поскольку заголовки часто содержат запятые.

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

Файл JSON содержит раздел плюс по одному объекту на каждый заголовок: текст заголовка, ссылку на статью, дату публикации и раздел. Заголовки и ссылки ниже, иллюстративные заполнители, а не реальные данные.

json
{
  "section": "Technology",
  "articles": [
    {
      "headline": "Chipmaker Delays Second Plant as Subsidies Stay in Flux",
      "link": "https://www.bloomberg.com/news/articles/example-chip-delay",
      "published": "2024-01-18",
      "section": "Technology"
    },
    {
      "headline": "Cloud Provider Posts Record Quarter on AI Demand",
      "link": "https://www.bloomberg.com/news/articles/example-cloud-quarter",
      "published": "2024-01-17",
      "section": "Technology"
    }
  ]
}

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

csv
headline,link,published,section
"Chipmaker Delays Second Plant as Subsidies Stay in Flux","https://www.bloomberg.com/news/articles/example-chip-delay","2024-01-18","Technology"
"Cloud Provider Posts Record Quarter on AI Demand","https://www.bloomberg.com/news/articles/example-cloud-quarter","2024-01-17","Technology"

Масштабирование на несколько разделов и страниц

Одна страница раздела, демонстрация; реальная задача отслеживает несколько площадок во времени. Bloomberg предоставляет набор публичных URL разделов (технологии, рынки, экономика, политика и другие), поэтому вы можете перебирать их в цикле, получать каждый через Crawling API, разбирать той же функцией и объединять результаты. Поскольку каждая страница раздела имеет одинаковую структуру листинга, написанный парсер работает для всех без изменений.

javascript
async function scrapeSections(sections) {
  const all = [];

  for (const path of sections) {
    const url = `https://www.bloomberg.com/${path}`;
    const html = await crawl(url);
    if (!html) continue;

    const { articles } = parseDataFromHTML(html);
    all.push(...articles);
    console.log(`${path}: ${articles.length} headlines`);

    // Pace requests so you stay under the rate limit
    await new Promise((r) => setTimeout(r, 2000));
  }

  return all;
}

// scrapeSections(['technology', 'markets', 'economics']);

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

Как избежать блокировки

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

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

Более широкое руководство доступно в статье о том, как парсить сайты без блокировки.

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

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

Это руководство намеренно ограничено публичными метаданными заголовков и ссылок: текстом заголовка, URL статьи, временной меткой публикации и разделом истории, всем, что видно на странице раздела без авторизации. Это принципиально отличается от самой статьи. Репортажи, аналитика и медиафайлы Bloomberg являются защищёнными авторским правом произведениями. Не парсите, не храните и не распространяйте полный текст статей, аннотации или изображения, и не создавайте производные архивы, воспроизводящие редакционный продукт Bloomberg. Собрать заголовок и ссылку, чтобы читатель мог перейти к оригиналу на bloomberg.com, нормальное использование со ссылкой; копирование тела за этой ссылкой, нет. Если какое-либо поле, которого вы касаетесь, связано с идентифицируемыми лицами, применяется законодательство о конфиденциальности, такое как GDPR и CCPA, поверх авторского права, ещё одна причина оставаться в рамках фактических метаданных листинга.

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

Итоги

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

  • Bloomberg отрисовывает листинги на стороне клиента и жёстко блокирует. Простой запрос возвращает пустую оболочку или проверку, поэтому необходимо отрисовать страницу за доверенным IP, используя JavaScript-токен, прежде чем её разбирать.
  • Crawling API делает оба в одном вызове. Он отрисовывает страницу в реальном браузере, ротирует резидентные IP и обрабатывает проверки, возвращая готовый HTML для разбора с помощью Cheerio.
  • Cheerio извлекает публичные поля. Сопоставьте каждый якорь /news/articles/, читайте заголовок, ссылку, временную метку публикации и раздел, дедублируйте по ссылке и ожидайте, что сгенерированные имена классов будут меняться.
  • Масштабируйтесь и экспортируйте. Перебирайте публичные URL разделов Bloomberg в цикле, задавайте темп запросов и записывайте структурированные записи в JSON и CSV; используйте асинхронный Crawler при увеличении объёма.
  • Только заголовки и ссылки. Текст и медиафайлы статей Bloomberg защищены авторским правом, поэтому никогда не парсите и не распространяйте тело, никогда не трогайте ничего за авторизацией или платным доступом, соблюдайте ToS и robots.txt и предпочитайте официальные или лицензированные ленты Bloomberg для продакшн-использования.

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

Какие данные можно собирать с Bloomberg с помощью этого скрапера?

Это руководство собирает только публичные метаданные листинга: заголовок статьи, ссылку, временную метку публикации и раздел, к которому подана история, всё, что видно на странице раздела Bloomberg без авторизации. Оно не собирает тело статьи, аннотации или медиафайлы, поскольку этот контент защищён авторским правом. Результат, набор ссылок и метаданных, который вы можете использовать для мониторинга публикаций и перехода к оригинальным историям.

Почему обычный запрос возвращает неполные данные с Bloomberg?

Потому что Bloomberg строит страницы разделов на стороне клиента с помощью JavaScript и бросает проверки автоматизированному трафику. Сырой HTTP-запрос с IP дата-центра обычно возвращает пустую оболочку или страницу блокировки вместо карточек историй. Чтобы получить полную страницу, необходимо отрисовать её за доверенным IP, именно это Crawling API делает за вас при использовании JavaScript-токена.

Можно ли парсить статьи Bloomberg, находящиеся за платным доступом?

Нет. Это руководство однозначно: никогда не парсите ничего за авторизацией или платным доступом. Закрытый контент ограничен условиями Bloomberg, а обход ограждения может иметь юридические последствия. Оставайтесь на публичных заголовках и ссылках, которые любой может видеть на странице раздела, и используйте официальные или лицензированные продукты Bloomberg, если вам нужен полный закрытый контент.

Мои селекторы возвращают пустые значения. Что изменилось?

Почти наверняка, разметка Bloomberg. Сгенерированные имена классов, такие как Eyebrow_sectionTitle-Wew2fboZsjA-, меняются без предупреждения, а страницы разделов часто перестраивают свои модули, поэтому селекторы, работавшие в прошлом месяце, могут сломаться. Повторно проверьте живую страницу в инструментах разработчика браузера, обновите селекторы в parseDataFromHTML, и всё снова заработает. Периодическое обслуживание селекторов, норма для любого продакшн-скрапера.

Можно ли создать скрапер Bloomberg на языке, отличном от JavaScript?

Да. В этом руководстве используется JavaScript с Cheerio, но тот же подход работает на любом языке. Crawling API имеет библиотеки и SDK для нескольких языков, поэтому вы получаете отрисованный HTML тем же способом и разбираете его любым HTML-парсером, предпочитаемым вашим стеком, например BeautifulSoup в Python. Селекторы и поля остаются теми же; меняется только синтаксис разбора.

Предлагает ли Bloomberg официальную информационную ленту?

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

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

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

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

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