TypeScript 做爬虫: 强烈推荐! 它继承了在 Node.js 环境下开发的所有优势,并通过强大的类型系统极大地提升了爬虫代码(尤其是数据处理和解析部分)的可靠性、可读性和可维护性。
TS的核心价值在于大型复杂系统,无论是前端工程还是爬虫系统。如果用户正在技术选型,可能需要强调渐进式迁移策略——爬虫可以先从JS开始,等逻辑复杂后再引入TS。
下面是我用 TypeScript 编写的简单网页爬虫示例,它会爬取指定网站的标题和所有链接。这个实现展示了 TypeScript 在爬虫开发中的类型安全优势:
import axios from 'axios';
import * as cheerio from 'cheerio';
// 定义爬取结果的数据结构
interface ScrapedData {
title: string;
links: string[];
}
/**
* 网页爬虫函数
* @param url 要爬取的网址
* @returns 包含标题和链接的爬取结果
*/
async function scrapeWebsite(url: string): Promise<ScrapedData> {
try {
// 1. 获取网页内容
const response = await axios.get(url);
const html = response.data;
// 2. 加载HTML内容到Cheerio
const $ = cheerio.load(html);
// 3. 提取页面标题 (类型安全)
const title = $('title').text().trim();
// 4. 提取所有链接 (类型安全)
const links: string[] = [];
$('a').each((index, element) => {
const href = $(element).attr('href');
if (href && isValidUrl(href)) {
links.push(href);
}
});
// 5. 返回结构化数据
return { title, links };
} catch (error) {
throw new Error(`爬取失败: ${error instanceof Error ? error.message : String(error)}`);
}
}
/**
* 验证URL格式 (辅助函数)
* @param url 待验证的URL字符串
* @returns 是否为有效URL
*/
function isValidUrl(url: string): boolean {
try {
new URL(url);
return true;
} catch {
return false;
}
}
// 执行爬虫示例
(async () => {
const targetUrl = 'https://example.com'; // 替换为目标网站
try {
console.log(`开始爬取: ${targetUrl}`);
const startTime = Date.now();
const result = await scrapeWebsite(targetUrl);
console.log(`爬取完成 (耗时: ${Date.now() - startTime}ms)`);
console.log('页面标题:', result.title);
console.log('发现链接数量:', result.links.length);
// 打印前5个链接
console.log('示例链接:');
result.links.slice(0, 5).forEach(link => console.log(' -', link));
} catch (error) {
console.error('爬虫错误:', error instanceof Error ? error.message : error);
}
})();
代码说明
1、依赖安装(先执行这些命令):
npm install axios cheerio typescript @types/node @types/cheerio
2、核心功能:
- 使用 Axios 获取网页内容
- 使用 Cheerio 解析 HTML(类似 jQuery 的 API)
- 类型安全的元素提取
- URL 格式验证
3、TypeScript 优势体现:
// 明确的数据结构定义
interface ScrapedData {
title: string;
links: string[];
}
// 类型安全的DOM操作
const href = $(element).attr('href'); // 自动推断为 string | undefined
if (href && isValidUrl(href)) { ... } // 类型守卫
4、扩展建议:
// 增加请求延迟防止被封
import { setTimeout } from 'timers/promises';
await setTimeout(1000); // 每次请求间隔1秒
// 处理相对路径链接
const absoluteUrl = new URL(href, baseUrl).href;
// 添加用户代理
const response = await axios.get(url, {
headers: {
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) ...'
}
});
进阶功能添加
要处理更复杂的网站(如需要登录或 JavaScript 渲染),可添加:
import puppeteer from 'puppeteer';
// 使用无头浏览器处理动态内容
async function scrapeDynamicPage(url: string) {
const browser = await puppeteer.launch();
const page = await browser.newPage();
await page.goto(url, { waitUntil: 'networkidle2' });
// 获取渲染后的内容
const content = await page.content();
// 使用Cheerio解析
const $ = cheerio.load(content);
// ...提取逻辑
await browser.close();
}
运行说明
1、将代码保存为 crawler.ts
2、编译执行:
tsc crawler.ts --target es2017 --module commonjs
node crawler.js
3、或使用 ts-node
直接运行:
npx ts-node crawler.ts
上面就是一个简单的爬虫案例,使用TypeScript可以有效提成爬虫代码的工作效率降低运行错误,结构清晰还会对错误类型精确检测。如果项目相对复杂,可以考虑分布式爬取(Apify)。