Forbes 是开放网络上最大的商业和财经新闻网站之一,覆盖行业、公司、市场及其背后的人物。其公开版块和话题页面承载着大量结构化信号:文章标题、作者、发布时间,以及每篇文章所属的话题。分析师通过这些列表追踪某个行业正在讨论的内容,内容团队用它来梳理报道格局和趋势,研究人员通过索引标题来追踪某个故事的走向。所有这些元数据都以可预测的布局呈现在公开列表页面上,无需打开任何一篇文章就可以获取。

本教程展示如何用 JavaScript 和 Node.js 配合 Cheerio 抓取 Forbes 数据。你将构建一个小型、可运行的爬虫,通过 Crawling API 获取 Forbes 公开话题或版块页面,解析每篇报道的标题、作者署名、文章链接、发布日期和版块信息,处理分页,并将结果导出为 JSON 和 CSV。整个教程仅限于公开列表元数据:仅限标题和链接,绝不涉及完整文章文字或媒体内容。末尾的合法性章节不是套话,因为 Forbes 内容受版权保护,请在将本代码用于任何实际规模之前先阅读。

你将构建什么

一个 Node.js 脚本,接受 Forbes 公开版块或话题 URL,通过 Crawling API 获取已渲染的 HTML,并从列表页面上的每张文章卡片中提取结构化记录。我们以技术版块作为运行示例,每篇报道提取以下字段:

  • 标题列表卡片上显示的文章题目。
  • 作者署名,卡片上标注的撰稿人或编辑记者。
  • 链接该文章的公开 URL。
  • 发布日期列表显示的文章日期或相对时间。
  • 版块列表所属的话题或频道,例如 technology 或 business。

请注意刻意省略的内容:文章正文、图片和任何媒体内容。本爬虫只采集链接和元数据,用于索引和追踪报道,而非版权内容本身。

为什么普通请求在 Forbes 上失败

如果你用裸 HTTP 客户端请求 Forbes 版块 URL,很少能得到文章卡片数据。有两个不利因素。第一,Forbes 在浏览器中用 JavaScript 加载大量列表内容,因此初始 HTML 在页面脚本运行之前近乎空白。第二,Forbes 能识别自动化流量:不像真实浏览器的数据中心 IP 和请求模式,在到达已渲染的列表之前就会被限速、挑战或封锁。

因此,一个可用的 Forbes 爬虫需要在一次请求中同时具备两样东西:一个能真正渲染页面的浏览器,以及一个被网站识别为真实访客的 IP。你可以自己搭建无头浏览器加轮换住宅代理池,但把它们组合起来并保持健康运行才是大部分工作。Crawling API 将两者折叠进一次调用:你把 URL 发过去,它在可信 IP 后面渲染页面,并返回已完成的 HTML 供你用 Cheerio 解析。

使用 JavaScript token

Crawling API 提供两种 token:普通 token 和 JavaScript token。Forbes 需要在真实浏览器中渲染页面,因此本教程中的每次请求都要使用你的 JavaScript token。普通 token 返回未渲染的空壳,你的选择器将一无所获。

前提条件

编写代码之前需要准备好几样东西,每样都不需要很长时间。

基础 JavaScript 和 Node.js。你应该能够编写和运行 Node 脚本,并用 npm 安装包。如果你是 Node 新手,我们关于用 Node.js 构建网络爬虫的指南涵盖了本教程所需的基础知识。

Node.js 16 或更高版本。node --version 确认你的版本。如果没有安装,请从 Node.js 官网或通过 nvm 等版本管理器安装。

Crawlbase 账号和 token。注册后打开控制台,复制你的 JavaScript token。免费层级提供 1000 次请求且无需绑定信用卡,只为成功的请求付费。把 token 当成密码对待:它用于验证你的请求,请不要提交到版本控制系统。

搭建项目

创建一个项目文件夹,初始化它,并安装爬虫所需的两个库。

bash
node --version

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

npm install crawlbase cheerio

两个依赖各司其职:crawlbase 是 Crawling API 的官方 Node 客户端,cheerio 用类似 jQuery 的 API 解析返回的 HTML,让你可以通过 CSS 选择器提取各个字段。在此文件夹中创建一个名为 scraper.js 的文件,然后将下面各步骤的代码添加进去。

步骤 1:获取已渲染的列表页面

首先获取完整页面。导入 CrawlingAPI 类,用你的 JavaScript token 初始化,并请求 Forbes 公开版块 URL。Forbes 在你滚动时加载卡片,因此传入 ajax_wait 和简短的 page_wait 可以告知 API 在返回前等待动态内容。在解析前检查状态码,可以让失败显而易见,而非悄无声息。

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

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

const forbesPageURL = 'https://www.forbes.com/technology/';

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

node scraper.js 运行脚本,你应该在正文顶部看到真实的 Forbes 列表标记,而非精简版的空壳。这能在你编写任何选择器之前确认渲染正常工作。Crawling API 使用你提供的 JavaScript token 在真实浏览器中渲染页面,而 ajax_wait 配合 page_wait 给延迟加载的卡片留出填充时间,确保文章链接在你取回的 HTML 中已经存在。

Crawlbase Crawling API

第一次请求就已经无需任何本地无头浏览器或代理,返回了一个完整渲染的 Forbes 版块页面。Crawling API 在真实浏览器中运行页面,在服务器端轮换住宅 IP,处理 Forbes 对爬虫发起的速率限制和挑战,只需一次调用就返回渲染完成的 HTML。先在免费层级向公开版块发起请求,再添加你的解析器。

步骤 2:用 Cheerio 解析每张文章卡片

拿到已渲染的 HTML,将其加载到 Cheerio 并遍历文章卡片。Forbes 将每篇报道放在一个流式条目中,标题链接是同一类型的 a.color-link 锚点,贯穿其所有列表,因此你选取每个文章链接,然后从每张卡片内或周围读取标题、作者署名、发布日期和版块信息。防御性地读取每个字段,可以避免单个缺失值导致整次运行崩溃。

javascript
const cheerio = require('cheerio');

function parseForbesData(html, section) {
  const $ = cheerio.load(html);
  const articles = [];
  const seen = new Set();

  // One record per article card in the listing stream
  $('article.stream-item').each((_, element) => {
    const card = $(element);

    const titleLink = card.find('a.color-link').first();
    const headline = titleLink.text().trim();
    let link = titleLink.attr('href') || '';
    if (link && link.startsWith('/')) {
      link = new URL(link, 'https://www.forbes.com').href;
    }

    const author = card.find('.stream-item__author').text().trim();
    const date = card.find('.stream-item__date').text().trim();

    // Skip empty cards and de-duplicate repeated links
    if (!headline || !link || seen.has(link)) return;
    seen.add(link);

    articles.push({
      headline,
      author: author || 'N/A',
      date: date || 'N/A',
      section: section || 'N/A',
      link,
    });
  });

  return articles;
}

有几个细节让这段代码忠实于页面内容。每篇报道位于一个 article.stream-item 中,标题链接是其中的 a.color-link 锚点,Forbes 旧版列表也沿用这同一类名。作者来自 .stream-item__author,发布日期来自 .stream-item__date。链接从锚点的 href 读取并解析为绝对 URL,以便在页面之外使用,而 Set 则过滤掉列表流中常见的重复链接。版块由调用方传入,因为你已经知道你请求的是哪个频道 URL。

选择器会漂移

Forbes 会定期发布标记变更,因此上述类名只是起始模板,而非固定合约。当某个字段返回为空时,在浏览器开发者工具中重新检查实时页面并更新选择器。定期维护选择器对任何生产爬虫来说都是正常的,不代表有什么问题。

步骤 3:组装完整脚本,导出 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' });

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

function toCsv(rows) {
  const headers = ['headline', 'author', 'date', 'section', '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 section = 'technology';
  const url = `https://www.forbes.com/${section}/`;
  const html = await crawl(url);
  if (!html) return;

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

main();

将步骤 2 中的 parseForbesData 函数粘贴到同一文件中,以便 main 可以调用它。用 node scraper.js 运行,你将得到两个文件:包含完整结构化记录的 forbes.json,以及可在电子表格中打开的 forbes.csvtoCsv 辅助函数为每个字段加引号,并将内嵌引号双写,这一点在这里很重要,因为标题中经常含有逗号。

输出结果示例

JSON 文件中每篇文章为一个对象,包含标题、作者署名、发布日期、版块和链接。以下数值为示意性占位符,非 Forbes 实时数据。

json
[
  {
    "headline": "How AI Startups Are Reshaping Enterprise Software",
    "author": "Jane Doe",
    "date": "Jun 10, 2026",
    "section": "technology",
    "link": "https://www.forbes.com/sites/example/2026/06/10/ai-startups-enterprise/"
  },
  {
    "headline": "The Quiet Rise Of Mid-Market Cloud Providers",
    "author": "John Smith",
    "date": "Jun 9, 2026",
    "section": "technology",
    "link": "https://www.forbes.com/sites/example/2026/06/09/mid-market-cloud/"
  }
]

CSV 文件以相同的行呈现,并附有表头行,可直接导入 Excel、Google Sheets 或任何读取分隔文件的数据流水线。

csv
headline,author,date,section,link
"How AI Startups Are Reshaping Enterprise Software","Jane Doe","Jun 10, 2026","technology","https://www.forbes.com/sites/example/2026/06/10/ai-startups-enterprise/"
"The Quiet Rise Of Mid-Market Cloud Providers","John Smith","Jun 9, 2026","technology","https://www.forbes.com/sites/example/2026/06/09/mid-market-cloud/"

处理分页

一个版块页面只够演示;真正的任务需要抓取第一批标题之外的更多内容。Forbes 版块页面通过页码查询参数暴露额外结果,因此你可以循环遍历页码,通过 Crawling API 获取每一页,用相同的函数解析,并在某页没有返回新文章时停止。由于每个列表页面共享相同的卡片结构,你已写好的解析器无需任何修改即可在所有页面上工作。

javascript
async function scrapeAllPages(section, maxPages) {
  const all = [];
  const seen = new Set();

  for (let page = 1; page <= maxPages; page++) {
    const url = `https://www.forbes.com/${section}/?page=${page}`;
    const html = await crawl(url);
    if (!html) break;

    const batch = parseForbesData(html, section)
      .filter((a) => !seen.has(a.link));
    if (batch.length === 0) break; // no new articles

    batch.forEach((a) => seen.add(a.link));
    all.push(...batch);
    console.log(`Page ${page}: ${batch.length} new articles`);

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

  return all;
}

确切的分页参数可能会变化,因此请在浏览器中查看几个真实的"下一页"链接并匹配其模式。重要的习惯可以推广到任何目标:循环直到结果耗尽,按链接去重以避免同一标题被存储两次,并在请求之间添加短暂延迟以避免猛敲网站。有关此类渲染型 JavaScript 密集页面的更多内容,请参阅我们关于爬取 JavaScript 网站的指南。

保持不被封锁

即使渲染问题已解决,Forbes 仍会监视爬虫形态的流量。以下几个习惯可以让运行保持健康,适用于任何高难度商业目标。

  • 控制请求节奏。在紧循环中猛敲版块是最快触及 Forbes 速率限制的方式,因此在页面获取之间引入延迟。分散请求是保持不被限速的最重要单一因素。
  • 善用轮换。住宅 IP 池将请求分散到许多真实用户地址上,避免单个地址触发限制或挑战。Crawling API 会为你处理这一切;如果你自建技术栈,这是最关键的环节。
  • 关注状态码。运行中开始返回挑战或非 200 响应,说明当前的速率或 IP 层级已经不够用了。把这当作需要退让的信号,而不是可以忽略的噪音。

更完整的方法请参阅如何在不被封锁的情况下抓取网站。如果想从其他新闻来源获取类似的标题元数据,相同的获取后解析模式可以直接应用到抓取 Google 新闻

抓取 Forbes 合法吗?

抓取 Forbes 是否被允许,取决于 Forbes 的服务条款、你所在的司法管辖区以及你对数据的用途。Forbes 的条款限制自动化访问和对其内容的再利用,因此无论你的工具多么谨慎,抓取行为都可能违反这些条款。这里的任何代码都不能改变这一事实,它只是让技术部分得以实现。请阅读 Forbes 的服务条款和其 robots.txt,遵守其声明的任何速率预期,并将两者视为你采集内容边界的依据。绝不抓取任何登录或付费墙后面的内容:付费和订阅专属文章超出范围,绕过访问控制来访问这些内容是一条更严重的红线。

本教程刻意将范围限定在公开列表元数据:任何人在版块页面上无需账号即可看到的标题、作者署名、公开文章链接、发布日期和版块信息。关键在于,它不采集文章正文、图片、图表或视频。Forbes 的文章和媒体内容是受版权保护的作品,复制或再发布完整文字或媒体是版权侵权,而非合理爬取。采集标题和链接以供索引、监控或回链至原文,与复制内容本身有本质区别。将存储数据限于事实和指针,注明并链接回来源,不要将 Forbes 的编辑内容作为你自己的内容呈现或置于你自己的付费墙后面。

如果你的项目需要公开标题和链接之外的内容,正确路径是获得授权,而非搭建更聪明的爬虫。Forbes 提供官方信息源以及许可和联合分发安排,用于在明确条款、署名规则和商业权利下再利用其内容。当你需要完整文字、大量数据、保证结构或再发布权利时,这些才是正确的工具。当你不确定某种使用方式是否被允许时,获取许可或数据协议,而非假设沉默即代表同意。

回顾

核心要点

  • Forbes 在客户端渲染列表且对流量进行防护。普通请求返回空壳或挑战页,因此必须使用 JavaScript token 在可信 IP 后面渲染页面,然后再进行解析。
  • Crawling API 在一次调用中完成两件事。它在真实浏览器中渲染页面,轮换住宅 IP,并等待延迟加载的卡片,返回你用 Cheerio 解析的渲染完成的 HTML。
  • Cheerio 提取元数据。选取每个 article.stream-item,从 a.color-link 锚点读取标题和链接,同时读取作者、日期和版块,并预期类名会漂移。
  • 分页并导出。循环遍历 Forbes 版块页面直到没有新文章出现,按链接去重,控制请求节奏,并将结构化记录写入 JSON 和 CSV。
  • 坚守公开元数据,尊重版权。只采集标题、链接、署名和日期,绝不采集文章正文或媒体,遵守服务条款、robots.txt 和付费墙,再利用时优先选择 Forbes 官方信息源或许可协议。

常见问题

我可以从 Forbes 提取数据吗?

你可以采集标题、文章链接、署名和发布日期等公开列表元数据,前提是遵守 Forbes 的服务条款和 robots.txt,不复制完整文章文字或媒体内容。将采集范围限于公开页面,绝不涉及任何登录或付费墙后面的内容,并在需要再利用内容时优先选择 Forbes 官方信息源或许可协议。本教程通过只存储标题和链接,而非文章正文,将范围保持在这些界限之内。

为什么普通请求从 Forbes 返回不完整的数据?

因为 Forbes 在客户端用 JavaScript 加载大量列表内容,并对自动化流量发起挑战。来自数据中心 IP 的原始 HTTP 请求通常返回空壳或封锁页,而非文章卡片。要获取完整页面,必须在可信 IP 后面渲染它,这正是当你使用 JavaScript token 配合 ajax_waitpage_wait 时 Crawling API 为你处理的事情。

为什么使用 Crawling API 而不是自己运行 Puppeteer?

像 Puppeteer 这样的无头浏览器可以渲染 Forbes,但你随后需要自己运行和维护浏览器集群、接入轮换住宅代理池,以及自己处理挑战,这是大部分工作,而且在大规模时速度很慢。Crawling API 将渲染、IP 轮换和挑战处理折叠进一次调用,你发送一个 URL,得到渲染完成的 HTML。你把时间花在解析上,而不是维护基础设施。

我的选择器返回空值。发生了什么变化?

几乎可以确定是 Forbes 的标记发生了变化。stream-item__author 等类名和 a.color-link 标题锚点会随时间变化,因此上个月有效的选择器可能已经失效。在浏览器开发者工具中重新检查实时页面,更新 parseForbesData 中的选择器,就可以恢复正常。定期维护选择器对任何生产爬虫来说都是正常的。

我可以抓取 Forbes 文章的完整文字吗?

不可以,你也不应该这样做。Forbes 文章和媒体内容受版权保护,复制和再发布正文、图片或视频是版权侵权,而非合理爬取。本教程只采集公开标题、链接、署名、日期和版块,以便你可以索引并回链至原文。如果你需要完整内容,请使用 Forbes 官方信息源或许可及联合分发协议,这些才能赋予爬虫永远无法提供的再利用权利。

抓取 Forbes 时会被封锁吗?

如果你从一个地址发送过多请求速度过快,是有可能的。Crawling API 通过轮换住宅 IP 和为你处理挑战来降低这一风险,但你仍然应该控制请求节奏,在页面之间添加延迟,并关注状态码,以便在挑战出现时及时退让。这些习惯对任何高难度商业目标都很重要。

开始构建

大规模爬取任何站点,无需与基础设施对抗。

Crawlbase 负责处理代理、指纹和 CAPTCHA,让你的团队专注于交付数据流水线,而非维护爬取管道。1,000 次请求免费,无需信用卡。

自助开通 · 无需销售通话 · 提供企业级爬取量