cparse

一个基于 Cheerio 的强大 HTML 解析和数据提取工具库,专为简化网页数据抓取而设计。
✨ 核心特性
🎯 语法糖增强
- 属性提取语法:
selector@attribute
- 直接提取属性值
- 数组提取语法:
[selector]
- 获取所有匹配元素
- 类条件简化:
selector[.class]
- 简化的类选择器
- 自定义伪选择器:
:not-empty
- 扩展的伪选择器
🔧 强大的过滤器系统
- 30+ 内置过滤器:数据类型转换、字符串处理、数组操作等
- 过滤器链:
selector | filter1 | filter2
- 链式数据处理
- 自定义过滤器:支持扩展自定义过滤器
🚀 Cheerio 功能扩展
- 扩展方法:
.string()
, .nextNode()
, .extract()
, .extractAll()
- HTTP 集成:Axios 和 Got 客户端无缝集成
- URL 处理:相对 URL 自动转换为绝对 URL
🛡️ 企业级特性
- 完善的错误处理:多种错误类型和详细错误信息
- 高性能设计:查询缓存、批量处理优化
- TypeScript 支持:完整的类型定义
- 全面测试:200+ 测试用例保证质量
📦 安装
npm install cparse
系统要求:Node.js >= 18.17.0
🚀 快速开始
基础用法
const { loadCheerio, parse } = require('cparse');
const html = '<div class="title">Hello World</div>';
const $ = loadCheerio(html);
const title = parse('.title', $);
const items = parse('[.item]', $);
const links = parse('[a@href]', $);
const price = parse('.price | trim | float', $);
结构化数据提取
const html = `
<div class="product">
<h2 class="title">iPhone 15</h2>
<span class="price">$999.00</span>
<div class="rating" data-score="4.5">★★★★☆</div>
</div>
`;
const $ = loadCheerio(html);
const product = parse({
title: '.title',
price: '.price | regex:\\d+\\.\\d+ | float',
rating: '.rating@data-score | float'
}, $);
console.log(product);
🔗 HTTP 客户端集成
Axios 集成
const axios = require('axios');
const { cheerioHookForAxios, parse } = require('cparse');
const client = axios.create();
cheerioHookForAxios(client);
const response = await client.get('https://example.com');
const title = parse('title', response.$);
const links = parse('[a@href]', response.$);
Got 集成
const got = require('got');
const { cheerioHookForGot, parse } = require('cparse');
const client = got.extend({});
cheerioHookForGot(client);
const response = await client.get('https://example.com');
const data = parse({
title: 'title',
description: 'meta[name="description"]@content'
}, response.$);
🎯 核心语法糖功能
cparse 的核心价值在于提供简洁的语法糖,简化常见的数据提取操作:
1. 属性提取语法 @
$('a').map((i, el) => $(el).attr('href')).get();
parse('[a@href]', $);
2. 数组提取语法 []
$('.item').map((i, el) => $(el).text()).get();
parse('[.item]', $);
3. 类条件简化 [.class]
$('div').filter('.active').text();
parse('div[.active]', $);
4. 自定义伪选择器
parse('p:not-empty', $);
🔧 强大的过滤器系统
cparse 提供了 30+ 内置过滤器,支持链式调用进行复杂的数据处理:
parse('.price | trim | regex:\\d+\\.\\d+ | float', $);
📊 过滤器分类
数据类型转换
int | 转换为整数 | parse('.count | int', $) |
float | 转换为浮点数 | parse('.price | float', $) |
bool | 转换为布尔值 | parse('.active | bool', $) |
字符串处理
trim | 去除首尾空白 | parse('.title | trim', $) |
slice | 字符串切片 | parse('.text | slice:0:10', $) |
regex | 正则表达式匹配 | parse('.text | regex:\\d+', $) |
replace | 字符串替换 | parse('.text | replace:old:new', $) |
split | 字符串分割 | parse('.text | split:,', $) |
upper/lower | 大小写转换 | parse('.text | upper', $) |
capitalize | 首字母大写 | parse('.text | capitalize', $) |
title | 标题格式化 | parse('.text | title', $) |
数组处理
length | 获取长度 | parse('[.items] | length', $) |
first/last | 首/末元素 | parse('[.items] | first', $) |
unique | 数组去重 | parse('[.items] | unique', $) |
sort | 数组排序 | parse('[.items] | sort', $) |
compact | 过滤空值 | parse('[.items] | compact', $) |
join | 数组连接 | parse('[.items] | join:-', $) |
特殊处理
date | 日期解析 | parse('.date | date', $) |
size | 尺寸解析 | parse('.filesize | size', $) |
number | 数字格式化 | parse('.price | number:2', $) |
📚 API 参考
核心函数
loadCheerio(html, options?, baseUrl?)
加载 HTML 并返回扩展的 Cheerio 实例
const $ = loadCheerio('<div>Hello</div>', {}, 'https://example.com');
parse(rule, $, filters?)
数据解析核心函数
parse('h1', $)
parse({ title: 'h1', links: '[a@href]' }, $)
parse(['[.item]', { name: '.name', price: '.price | float' }], $)
HTTP 集成
cheerioHookForAxios(instance, options?)
为 Axios 添加 Cheerio 支持
cheerioHookForGot(instance, options?)
为 Got 添加 Cheerio 支持
🎯 查询语法详解
基础语法
selector | 标准 CSS 选择器 | parse('h1', $) |
selector@attr | 属性提取语法糖 | parse('a@href', $) |
[selector] | 数组提取语法糖 | parse('[.item]', $) |
selector | filter | 过滤器链 | parse('.price | float', $) |
语法糖功能
1. 类条件简化
parse('div[.active]', $)
parse('div.active', $)
2. 自定义伪选择器
parse('p:not-empty', $)
parse('p:not(:empty)', $)
3. 复杂选择器支持
parse('nav > ul > li:first-child', $)
parse('input[type="text"]:focus', $)
parse('p:contains("重要")', $)
高级用法
结构化数据提取
const data = parse({
title: 'h1',
price: '.price | float',
tags: '[.tag]',
link: 'a@href'
}, $);
分割器语法(列表处理)
const items = parse([
'[.product]',
{
name: '.name',
price: '.price | float',
inStock: '.stock | bool'
}
], $);
函数处理
const result = parse([
'.content',
text => text.toUpperCase(),
text => text.trim()
], $);
🚀 Cheerio 扩展方法
cparse 为 Cheerio 添加了便捷的扩展方法:
扩展方法列表
.string() | 纯文本内容(不含子元素标签) | $('.content').string() |
.nextNode() | 下一个兄弟节点的文本 | $('.label').nextNode() |
.extract(attr) | 提取单个元素的属性/内容 | $('.item').extract('href') |
.extractAll(attr) | 提取所有元素的属性/内容 | $('.items').extractAll('text') |
特殊属性值
在 extract()
和 extractAll()
中可使用的特殊属性:
text
: 文本内容
html
: HTML 内容
outerHtml
: 包含元素本身的 HTML
string
: 纯文本内容
nextNode
: 下一个兄弟节点文本
🛡️ 错误处理
cparse 提供完善的错误处理机制:
错误类型
- QueryParseError: 查询语法错误
- FilterError: 过滤器执行错误
- ValidationError: 参数验证错误
try {
parse('.text | unknownFilter', $);
} catch (error) {
if (error.name === 'FilterError') {
console.log(`过滤器错误: ${error.filterName}`);
console.log(`可用过滤器: ${error.context.availableFilters}`);
}
}
⚡ 性能优化
自动查询缓存
parse('h1', $);
parse('h1', $);
批量处理建议
const data = parse({
titles: '[h1]',
links: '[a@href]',
prices: '[.price | float]'
}, $);
🔄 重构优化
v2.0.0 重大更新
🎯 核心优化
- 移除重复实现:删除与 Cheerio 原生功能重复的代码
- 专注语法糖:保留真正有价值的语法糖功能
- 性能提升:直接使用 Cheerio 原生选择器,性能更优
- 代码简化:代码量减少 40%,维护性大幅提升
🚀 保留的核心价值
- ✅ 属性提取语法:
selector@attribute
- ✅ 数组提取语法:
[selector]
- ✅ 类条件简化:
selector[.class]
- ✅ 自定义伪选择器:
:not-empty
- ✅ 强大的过滤器系统
- ✅ 结构化数据提取
- ✅ HTTP 客户端集成
🗑️ 移除的重复功能
- ❌ 条件查询处理(Cheerio 原生支持)
- ❌ 嵌套查询处理(Cheerio 原生支持)
- ❌ 伪选择器重复实现(Cheerio 原生支持)
🤝 贡献
欢迎提交 Issue 和 Pull Request!
开发环境
git clone https://github.com/your-username/cparse.git
npm install
npm test
npm run lint
📄 许可证
MIT License - 详见 LICENSE 文件
⭐ 如果这个项目对你有帮助,请给个 Star!
2.0.1 (2024-12-16)
🎯 重大重构优化版本
这是 2.0.0 的优化版本,完成了彻底的重构工作,移除了与 Cheerio 原生功能重复的实现,专注于提供真正有价值的语法糖和过滤器功能。
✨ 核心改进
- 代码简化:移除重复实现,代码量减少 40%
- 性能提升:直接使用 Cheerio 原生选择器,性能大幅提升
- 专注核心:保留语法糖和过滤器系统的核心价值
- 文档重构:README 全面重新组织,突出核心功能
🚀 性能表现
- HTML 加载:53.78ms/次
- 选择器解析:6.06ms/次
- 复杂对象提取:31.28ms/次
- 内存优化:减少 32.24MB
🧪 质量保证
- 203 个测试用例全部通过
- 8 个测试套件全部通过
- 代码质量检查通过