UNPKG

cparse

Version:

一个基于 Cheerio 的 HTML 解析和数据提取工具库

310 lines (222 loc) 7.05 kB
# API 参考文档 ## 核心函数 ### loadCheerio(html, options?, baseUrl?) 加载HTML字符串并返回扩展的Cheerio实例。 **参数:** - `html` (string): HTML字符串 - `options` (object, 可选): Cheerio选项 - `keepRelativeUrl` (boolean): 是否保持相对URL,默认false - `xmlMode` (boolean): 是否使用XML模式,默认false - `decodeEntities` (boolean): 是否解码HTML实体,默认true - `baseUrl` (string, 可选): 基础URL,用于转换相对URL为绝对URL **返回:** 扩展的Cheerio实例 **示例:** ```javascript const { loadCheerio } = require('cparse'); const $ = loadCheerio('<div>Hello</div>'); const $withBase = loadCheerio('<a href="/page">Link</a>', {}, 'https://example.com'); ``` ### parse(rule, $, filters?) 解析数据的核心函数。 **参数:** - `rule` (string|object|array|function): 解析规则 - string: CSS选择器查询 - object: 对象结构解析 - array: 分割器语法 `[selector, structure]` - function: 自定义处理函数 - `$` (Cheerio): Cheerio实例 - `filters` (object, 可选): 自定义过滤器对象 **返回:** 解析结果,类型取决于规则 **示例:** ```javascript const { parse, loadCheerio } = require('cparse'); const $ = loadCheerio('<div class="title">Hello World</div>'); // 字符串规则 const title = parse('.title', $); // "Hello World" // 对象规则 const data = parse({ title: '.title', count: '.count | int' }, $); // 分割器规则 const items = parse([ '[.item]', { name: '.name', price: '.price | float' } ], $); ``` ## HTTP客户端集成 ### cheerioHookForAxios(axiosInstance, options?) 为Axios实例添加Cheerio支持。 **参数:** - `axiosInstance`: Axios实例 - `options` (object, 可选): Cheerio选项 **示例:** ```javascript const axios = require('axios'); const { cheerioHookForAxios } = require('cparse'); const client = axios.create(); cheerioHookForAxios(client); const response = await client.get('https://example.com'); const title = response.$('title').text(); ``` ### cheerioHookForGot(gotInstance, options?) 为Got实例添加Cheerio支持。 **参数:** - `gotInstance`: Got实例 - `options` (object, 可选): Cheerio选项 **示例:** ```javascript const got = require('got'); const { cheerioHookForGot } = require('cparse'); const client = got.extend({}); cheerioHookForGot(client); const response = await client.get('https://example.com'); const title = response.$('title').text(); ``` ## Cheerio扩展方法 ### .string() 提取元素的纯文本内容,不包括子元素的HTML标签。 **返回:** string **示例:** ```javascript $('<div>Hello <span>World</span></div>').string(); // "Hello " ``` ### .nextNode() 获取下一个兄弟节点的文本值。 **返回:** string **示例:** ```javascript $('<div>Label: <span>Value</span></div>').find('div').nextNode(); // "Value" ``` ### .extract(attr?) 提取单个元素的指定属性或内容。 **参数:** - `attr` (string, 可选): 属性名,默认为'text' **返回:** any **支持的属性:** - `text`: 文本内容 - `html`: HTML内容 - `outerHtml`: 包含元素本身的HTML - `string`: 纯文本内容 - `nextNode`: 下一个兄弟节点文本 - 任何HTML属性名 **示例:** ```javascript $('.item').extract(); // 文本内容 $('.item').extract('html'); // HTML内容 $('.item').extract('href'); // href属性 ``` ### .extractAll(attr?) 提取所有匹配元素的指定属性或内容。 **参数:** - `attr` (string, 可选): 属性名,默认为'text' **返回:** Array **示例:** ```javascript $('.items').extractAll(); // 所有元素的文本内容数组 $('.items').extractAll('href'); // 所有元素的href属性数组 ``` ## 错误处理 ### 错误类型 #### ParseError ```javascript class ParseError extends Error { constructor(message, details = {}) // 属性: name, message, details } ``` #### QueryParseError ```javascript class QueryParseError extends ParseError { constructor(message, query, details = {}) // 属性: name, message, query, details } ``` #### FilterError ```javascript class FilterError extends ParseError { constructor(message, filterName, value, details = {}) // 属性: name, message, filterName, value, details } ``` #### ValidationError ```javascript class ValidationError extends ParseError { constructor(message, field, value, details = {}) // 属性: name, message, field, value, details } ``` ### Validator类 #### Validator.validateQuery(query) 验证查询字符串。 **参数:** - `query` (any): 待验证的查询 **返回:** string - 验证后的查询字符串 **抛出:** ValidationError #### Validator.validateSelector(selector) 验证选择器。 **参数:** - `selector` (any): 待验证的选择器 **返回:** string|null - 验证后的选择器 **抛出:** ValidationError #### Validator.validateFilterName(filterName, availableFilters?) 验证过滤器名称。 **参数:** - `filterName` (any): 待验证的过滤器名称 - `availableFilters` (object, 可选): 可用过滤器对象 **返回:** string - 验证后的过滤器名称 **抛出:** ValidationError ### ErrorHandler类 #### ErrorHandler.wrap(fn, context?) 包装函数以提供统一的错误处理。 **参数:** - `fn` (Function): 要包装的函数 - `context` (string, 可选): 错误上下文 **返回:** Function - 包装后的函数 #### ErrorHandler.safeExecute(fn, defaultValue?) 安全执行函数,返回结果或默认值。 **参数:** - `fn` (Function): 要执行的函数 - `defaultValue` (any, 可选): 默认返回值 **返回:** any - 执行结果或默认值 #### ErrorHandler.formatError(error) 格式化错误信息。 **参数:** - `error` (Error): 错误对象 **返回:** Object - 格式化的错误信息 ## 查询语法详解 ### 基本选择器 - `h1`: 选择第一个h1元素 - `.class`: 选择第一个class类元素 - `#id`: 选择id元素 - `[selector]`: 选择所有匹配的元素 ### 属性提取 - `selector@attr`: 提取指定属性 - `selector@text`: 提取文本内容(默认) - `selector@html`: 提取HTML内容 - `selector@outerHtml`: 提取包含元素的HTML ### 条件查询 - `selector[.class]`: 包含指定类 - `selector[attr]`: 包含指定属性 - `selector[attr=value]`: 属性值匹配 - `selector:first`: 第一个元素 - `selector:last`: 最后一个元素 - `selector:empty`: 空元素 - `selector:contains("text")`: 包含文本 ### 嵌套查询 - `parent > child`: 直接子元素 - `a > b > c`: 多级嵌套 ### 过滤器 - `selector | filter`: 应用单个过滤器 - `selector | filter1 | filter2`: 过滤器链 - `selector | filter:arg1:arg2`: 带参数的过滤器 ## 性能考虑 ### 查询缓存 - 解析后的查询会自动缓存 - 缓存大小限制为1000个条目 - 使用 `queryParser.clearCache()` 清理缓存 ### 最佳实践 1. 使用具体的选择器而不是通用选择器 2. 批量提取数据而不是多次单独查询 3. 合理使用过滤器链 4. 对于大量数据,考虑分批处理