在 Bun 环境下实现一个网络爬虫是个不错的想法。Bun 提供了内置的 fetch API,使得发送 HTTP 请求变得非常简单。以下是一个基本的网络爬虫实现,它可以爬取指定网页的内容并提取所有链接:

  1. 首先,创建一个新的 Bun 项目:
mkdir bun-web-crawler
cd bun-web-crawler
bun init
  1. 安装必要的依赖。我们将使用 cheerio 来解析 HTML:
bun add cheerio
  1. 创建一个名为 crawler.ts 的文件,并添加以下代码:
import { load } from 'cheerio';
 
async function crawl(url: string, depth: number = 0, maxDepth: number = 2) {
  if (depth > maxDepth) return;
 
  console.log(`Crawling: ${url}`);
 
  try {
    const response = await fetch(url);
    const html = await response.text();
    const $ = load(html);
 
    // 提取并打印页面标题
    const title = $('title').text();
    console.log(`Title: ${title}`);
 
    // 提取所有链接
    const links = $('a')
      .map((i, el) => $(el).attr('href'))
      .get()
      .filter((href): href is string => typeof href === 'string')
      .map(href => new URL(href, url).href)
      .filter(href => href.startsWith('http'));
 
    console.log(`Found ${links.length} links`);
 
    // 递归爬取链接
    for (const link of links) {
      await crawl(link, depth + 1, maxDepth);
    }
  } catch (error) {
    console.error(`Error crawling ${url}:`, error);
  }
}
 
// 开始爬取
const startUrl = 'https://example.com';
crawl(startUrl);
  1. 运行爬虫:
bun run crawler.ts

这个简单的爬虫会执行以下操作:

  1. 发送 HTTP 请求获取指定 URL 的内容。
  2. 使用 Cheerio 解析 HTML 内容。
  3. 提取并打印页面标题。
  4. 提取页面中的所有链接。
  5. 递归爬取找到的链接,直到达到最大深度。

注意事项:

  • 这个爬虫是一个基本实现,没有考虑很多实际情况,如重复 URL、速率限制等。
  • 在实际使用中,你应该遵守网站的 robots. Txt 规则和爬虫礼仪。
  • 对于大规模爬取,你可能需要添加并发控制、URL 队列管理、数据存储等功能。

增强功能:

  1. 添加延迟以避免过快请求:
function delay(ms: number) {
  return new Promise(resolve => setTimeout(resolve, ms));
}
 
// 在每次请求前添加延迟
await delay(1000); // 1秒延迟
  1. 使用 Set 来避免重复爬取:
const crawledUrls = new Set<string>();
 
async function crawl(url: string, depth: number = 0, maxDepth: number = 2) {
  if (depth > maxDepth || crawledUrls.has(url)) return;
  crawledUrls.add(url);
 
  // ... 其余代码 ...
}
  1. 添加错误处理和重试机制:
async function crawlWithRetry(url: string, depth: number, maxDepth: number, retries: number = 3