ワンクリックで
发票专用解析技能。支持中国增值税发票、普通发票、电子发票的结构化提取。基于 pdfjs-dist 实现坐标提取,可提取发票号码、日期、买卖双方信息、商品明细、金额等字段。
npx skills add https://github.com/ErixWong/touwaka-ai-mate --skill fapiaoこのコマンドをClaude Codeにコピー&ペーストしてスキルをインストール
发票专用解析技能。支持中国增值税发票、普通发票、电子发票的结构化提取。基于 pdfjs-dist 实现坐标提取,可提取发票号码、日期、买卖双方信息、商品明细、金额等字段。
npx skills add https://github.com/ErixWong/touwaka-ai-mate --skill fapiaoこのコマンドをClaude Codeにコピー&ペーストしてスキルをインストール
PDF 文件处理(Python 版)。使用 PyMuPDF 实现,内存效率高,适合处理大文件。用于读取、提取文本/表格/图片、合并、拆分、旋转、水印、加密/解密、页面渲染。当用户提到 .pdf 文件或需要操作 PDF 时触发。
PDF 文件处理。用于读取、提取文本/表格/图片、合并、拆分、旋转、水印、加密/解密、表单填写、页面渲染。当用户提到 .pdf 文件或需要操作 PDF 时触发。
Word 文档处理。用于读取、写入、编辑、模板填充 .docx 文件。支持页眉页脚、超链接、目录、图片操作。使用 Patcher API 保留原文档样式。当用户需要操作 Word 文档时触发。
ZIP file operations for creating and extracting archives.
ECharts 图表生成。用于需要可视化数据展示的场景,支持 20+ 图表类型(柱状图、折线图、饼图、雷达图等),输出 SVG/PNG/Base64/文件格式。当用户需要生成图表、数据可视化、统计图形时触发。
PowerPoint 演示文稿处理。用于读取现有 PPTX 信息、创建新演示文稿、提取媒体文件。支持文本、图片、表格、图表、形状、媒体、演讲者备注。当用户提到 .pptx 文件或需要操作 PowerPoint 时触发。
| name | fapiao |
| description | 发票专用解析技能。支持中国增值税发票、普通发票、电子发票的结构化提取。基于 pdfjs-dist 实现坐标提取,可提取发票号码、日期、买卖双方信息、商品明细、金额等字段。 |
| license | Proprietary. LICENSE.txt has complete terms |
| argument-hint | extract [path] [format] |
| user-invocable | true |
依赖:pdfjs-dist (Mozilla PDF.js) - 提供坐标提取能力
注意:本技能专门用于发票解析,与通用 PDF 处理技能 (
本技能提供 extract 工具,用于提取发票结构化数据。
参数:
| 参数 | 类型 | 必需 | 默认值 | 描述 |
|---|---|---|---|---|
path | string | 是 | - | PDF发票文件路径 |
format | string | 否 | json | 输出格式:json 或 markdown |
output | string | 否 | - | 输出文件路径(不指定则只返回内容) |
返回字段:
| 字段 | 类型 | 描述 |
|---|---|---|
success | boolean | 是否成功(提取到至少一个关键字段为 true) |
failure_reason | string|null | 失败原因码(NO_TEXT_LAYER, PARSE_INCOMPLETE, FILE_NOT_FOUND 等) |
message | string|null | 失败时可读的消息 |
text_content_length | number | 提取到的文本总长度(用于判断是否为扫描件) |
extraction_status | string | 提取状态:SUCCESS 或 NO_TEXT_LAYER |
invoice_number | string | 发票号码(8位或20位数字) |
invoice_date | string | 开票日期(格式:xxxx年xx月xx日,支持多种输入格式) |
invoice_type | string | 发票类型(识别增值税专票/普票、电子发票等多种类型) |
seller | object | 销售方信息 { name, taxId } |
buyer | object | 购买方信息 { name, taxId } |
total_amount | number | 合计金额 |
total_tax | number | 税额 |
total_with_tax | number | 价税合计(含一致性校验) |
item_count | number | 商品明细总数 |
page_count | number | PDF页数 |
remarks | string | 备注信息 |
field_sources | object | 关键字段来源页映射 { invoiceNumber, invoiceDate, ... } |
error | object|null | 异常详情 { code, stage, message, cause }(仅失败时) |
content | string | 格式化后的内容(JSON或Markdown) |
output_file | string | 保存的文件路径(如果指定了output参数) |
// JSON 格式输出
fapiao__extract({
path: "invoice.pdf",
format: "json"
})
// Markdown 格式输出
fapiao__extract({
path: "invoice.pdf",
format: "markdown"
})
// 保存到文件
fapiao__extract({
path: "invoice.pdf",
format: "json",
output: "invoice_result.json"
})
成功示例:
{
"success": true,
"failure_reason": null,
"message": null,
"text_content_length": 1423,
"extraction_status": "SUCCESS",
"invoice_number": "26512000000351324826",
"invoice_date": "2024年03月15日",
"invoice_type": "电子发票(增值税专用发票)",
"seller": {
"name": "某某科技有限公司",
"taxId": "91110108MA00XXXXXX"
},
"buyer": {
"name": "某某集团有限公司",
"taxId": "91110000123456789X"
},
"total_amount": 10000.00,
"total_tax": 1300.00,
"total_with_tax": 11300.00,
"item_count": 5,
"page_count": 1,
"remarks": "",
"field_sources": {
"invoiceNumber": 1,
"invoiceDate": 1,
"buyer": 1,
"seller": 1,
"amount": 1
},
"content": "{...}",
"format": "json"
}
扫描件示例:
{
"success": false,
"failure_reason": "NO_TEXT_LAYER",
"message": "PDF has no text layer (scanned image). Use OCR or VL model first.",
"text_content_length": 0,
"extraction_status": "NO_TEXT_LAYER",
"invoice_number": "",
"invoice_date": "",
"invoice_type": "",
"seller": { "name": "", "taxId": "" },
"buyer": { "name": "", "taxId": "" },
"total_amount": 0,
"total_tax": 0,
"total_with_tax": 0,
"item_count": 0,
"page_count": 1,
"remarks": "",
"output_file": null,
"content": "",
"format": "json"
}
异常示例:
{
"success": false,
"failure_reason": "FILE_NOT_FOUND",
"message": "Cannot read file: /path/to/missing.pdf",
"error": {
"code": "FILE_NOT_FOUND",
"stage": "pdf_read",
"message": "Cannot read file: /path/to/missing.pdf",
"cause": "ENOENT: no such file or directory"
}
}
对于多页发票,商品明细按页分组,每页包含:
{
"pageNumber": 1,
"issuer": "张三",
"itemCount": 3,
"items": [
{
"category": "*软件*",
"name": "企业管理软件",
"model": "V3.0",
"unit": "套",
"quantity": 1,
"price": 5000.00,
"amount": 5000.00,
"taxRate": "13%",
"taxAmount": 650.00
}
]
}
本技能基于 pdfjs-dist 的底层 API 实现坐标提取:
const page = await pdfDocument.getPage(1);
const textContent = await page.getTextContent();
const items = textContent.items.map(item => ({
text: item.str,
x: item.transform[4], // x坐标
y: item.transform[5], // y坐标
width: item.width,
height: item.height
}));
path.relative + .. 边界判断 + realpath 双端校验,防止前缀欺骗和软链绕过YYYY年MM月DD日、YYYY-MM-DD、YYYY.MM.DD、YYYY/MM/DD 及 token 拼接¥/¥ 符号 + "价税合计"/"小写"标签 + 合计行 + 一致性校验* 起始,允许 category 为空{ code, stage, message, cause } 结构化异常| 类型 | 支持状态 | 说明 |
|---|---|---|
| 增值税专用发票 | ✅ 完整支持 | 标准布局 |
| 增值税普通发票 | ✅ 完整支持 | 与专票布局相同 |
| 电子发票(专票) | ✅ 完整支持 | 关键字识别 |
| 电子发票(普票) | ✅ 完整支持 | 关键字识别 |
| 机动车销售统一发票 | ✅ 支持 | 关键字识别 |
| 二手车销售统一发票 | ✅ 支持 | 关键字识别 |
| 多页发票 | ✅ 完整支持 | 提取每页开票人信息 |
扫描版发票:本技能基于文本坐标解析。当 extraction_status === 'NO_TEXT_LAYER' 时表示没有文本层(纯图片扫描件),返回 success: false。建议先用 pdf 技能的 render 操作将页面转为图片,再使用 VL 模型识别。
非标准布局:如果发票布局与标准增值税发票差异较大,解析结果可能不准确。
坐标精度:PDF 坐标系原点在左下角,y 轴向上递增,与屏幕坐标系不同。
// 场景:扫描版发票处理
// 1. 先用 fapiao 技能尝试提取(会返回 NO_TEXT_LAYER 状态)
const result = await fapiao__extract({ path: "scanned_invoice.pdf" });
if (result.extraction_status === 'NO_TEXT_LAYER') {
// 处理扫描件...
}
// 2. 用 pdf skill 渲染页面
const renderResult = await pdf__read({
path: "scanned_invoice.pdf",
operation: "render",
output_dir: "./invoice_images"
});
// 3. 将图片发送给 VL 模型识别文字
| 错误码 | 描述 |
|---|---|
NO_TEXT_LAYER | PDF 无文本层(扫描件) |
PARSE_INCOMPLETE | 解析不完整,未提取到关键字段 |
PATH_NOT_ALLOWED | 路径不在允许范围内(含前缀欺骗/软链绕过检测) |
FILE_NOT_FOUND | 文件不存在或不可读 |
PDF_READ_ERROR | PDF 解析失败 |
UNEXPECTED_ERROR | 未预期的运行时错误 |
| 任务 | 调用方式 |
|---|---|
| 提取发票JSON数据 | fapiao__extract({ path: "invoice.pdf", format: "json" }) |
| 提取发票Markdown | fapiao__extract({ path: "invoice.pdf", format: "markdown" }) |
| 保存到文件 | fapiao__extract({ path: "invoice.pdf", output: "result.json" }) |
2026-05-30: 架构审计修复版本
path.relative + realpath 双端校验替代 startsWithtext_content_length + extraction_status(NO_TEXT_LAYER)success 语义:失败返回 success: false + failure_reason-、.、/ 及 token 拼接多格式field_sources 来源页{ code, stage, message, cause }2026-03-31: 初始版本,支持中国增值税发票解析
本技能基于 pdfjs-dist (Mozilla PDF.js) 开发,遵循 Touwaka Mate Skill 规范。