Files
lyxy-document/openspec/changes/archive/2026-03-08-unify-document-readers/specs/html-reader/spec.md
lanyuanxiaoyao 833018d451 feat: 统一文档解析器项目 - 迁移 lyxy-reader-office 和 lyxy-reader-html
## 功能特性

- 建立统一的项目结构,包含 core/、readers/、utils/、tests/ 模块
- 迁移 lyxy-reader-office 的所有解析器(docx、xlsx、pptx、pdf)
- 迁移 lyxy-reader-html 的所有解析器(html、url 下载)
- 统一 CLI 入口为 lyxy_document_reader.py
- 统一 Markdown 后处理逻辑
- 按文件类型组织 readers,每个解析器独立文件
- 依赖分组按文件类型细分(docx、xlsx、pptx、pdf、html、http)
- PDF OCR 解析器优先,无参数控制
- 使用 logging 模块替代简单 print
- 设计完整的单元测试结构
- 重写项目文档

## 新增目录/文件

- core/ - 核心模块(异常体系、Markdown 工具、解析调度器)
- readers/ - 格式阅读器(base.py + docx/xlsx/pptx/pdf/html)
- utils/ - 工具函数(文件类型检测)
- tests/ - 测试(conftest.py + test_core/ + test_readers/ + test_utils/)
- lyxy_document_reader.py - 统一 CLI 入口

## 依赖分组

- docx - DOCX 文档解析支持
- xlsx - XLSX 文档解析支持
- pptx - PPTX 文档解析支持
- pdf - PDF 文档解析支持(含 OCR)
- html - HTML/URL 解析支持
- http - HTTP/URL 下载支持
- office - Office 格式组合(docx/xlsx/pptx/pdf)
- web - Web 格式组合(html/http)
- full - 完整功能
- dev - 开发依赖
2026-03-08 13:46:37 +08:00

189 lines
6.0 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
## ADDED Requirements
### Requirement: HTML 文档解析
系统 SHALL 支持解析 HTML 格式文档和 URL 网页,按优先级尝试多个解析器。
#### Scenario: 按优先级尝试解析器
- **WHEN** 解析 HTML 内容
- **THEN** 系统按 trafilatura → domscribe → markitdown → html2text 的顺序尝试
#### Scenario: 成功解析
- **WHEN** 任一解析器成功
- **THEN** 系统返回解析结果
#### Scenario: 所有解析器失败
- **WHEN** 所有解析器均失败
- **THEN** 系统返回失败列表并退出非零状态码
### Requirement: URL 下载
系统 SHALL 支持从 URL 下载网页内容,按优先级尝试多个下载器。
#### Scenario: 按优先级尝试下载器
- **WHEN** 输入为 URL
- **THEN** 系统按 pyppeteer → selenium → httpx → urllib 的顺序尝试下载
#### Scenario: 成功下载
- **WHEN** 任一下载器成功
- **THEN** 系统返回 HTML 内容
#### Scenario: 所有下载器失败
- **WHEN** 所有下载器均失败
- **THEN** 系统返回失败列表并退出非零状态码
### Requirement: HTML 内容清理
系统 SHALL 在解析前清理 HTML 内容,移除不需要的标签和属性。
#### Scenario: 移除 script 标签
- **WHEN** HTML 内容包含 script 标签
- **THEN** 系统移除所有 script 标签
#### Scenario: 移除 style 标签
- **WHEN** HTML 内容包含 style 标签
- **THEN** 系统移除所有 style 标签
#### Scenario: 移除 svg 标签
- **WHEN** HTML 内容包含 svg 标签
- **THEN** 系统移除所有 svg 标签
#### Scenario: 移除 link 标签
- **WHEN** HTML 内容包含 link 标签
- **THEN** 系统移除所有 link 标签
#### Scenario: 移除 URL 属性
- **WHEN** HTML 标签包含 href、src、srcset、action 属性
- **THEN** 系统移除这些属性
#### Scenario: 移除 style 属性
- **WHEN** HTML 标签包含 style 属性
- **THEN** 系统移除所有 style 属性
#### Scenario: 移除 data-href 属性
- **WHEN** HTML 标签包含 data-href 属性
- **THEN** 系统移除这些属性
#### Scenario: 清理 title 属性中的 URL
- **WHEN** HTML 标签的 title 属性包含 URL
- **THEN** 系统移除 URL
#### Scenario: 清理包含 URL 的 class 属性
- **WHEN** HTML 标签的 class 属性包含 URL 样式
- **THEN** 系统移除这些 class
### Requirement: pyppeteer 下载器
系统 SHALL 支持使用 pyppeteer 下载 URL支持 JS 渲染)。
#### Scenario: pyppeteer 下载成功
- **WHEN** pyppeteer 库可用且 URL 可访问
- **THEN** 系统返回渲染后的 HTML 内容
#### Scenario: pyppeteer 库未安装
- **WHEN** pyppeteer 库未安装
- **THEN** 系统尝试下一个下载器
### Requirement: selenium 下载器
系统 SHALL 支持使用 selenium 下载 URL支持 JS 渲染)。
#### Scenario: selenium 下载成功
- **WHEN** selenium 库可用、LYXY_CHROMIUM_DRIVER 和 LYXY_CHROMIUM_BINARY 环境变量配置正确且 URL 可访问
- **THEN** 系统返回渲染后的 HTML 内容
#### Scenario: selenium 依赖未满足
- **WHEN** selenium 库未安装或环境变量未配置
- **THEN** 系统尝试下一个下载器
### Requirement: httpx 下载器
系统 SHALL 支持使用 httpx 下载 URL轻量级 HTTP 客户端)。
#### Scenario: httpx 下载成功
- **WHEN** httpx 库可用且 URL 可访问
- **THEN** 系统返回 HTML 内容
#### Scenario: httpx 库未安装
- **WHEN** httpx 库未安装
- **THEN** 系统尝试下一个下载器
### Requirement: urllib 下载器
系统 SHALL 支持使用 urllib 下载 URL标准库兜底方案
#### Scenario: urllib 下载成功
- **WHEN** URL 可访问
- **THEN** 系统返回 HTML 内容
#### Scenario: urllib 下载失败
- **WHEN** urllib 下载失败
- **THEN** 系统返回失败信息
### Requirement: trafilatura 解析器
系统 SHALL 支持使用 trafilatura 解析 HTML。
#### Scenario: trafilatura 解析成功
- **WHEN** trafilatura 库可用且 HTML 有效
- **THEN** 系统返回 Markdown 内容
#### Scenario: trafilatura 库未安装
- **WHEN** trafilatura 库未安装
- **THEN** 系统尝试下一个解析器
### Requirement: domscribe 解析器
系统 SHALL 支持使用 domscribe 解析 HTML。
#### Scenario: domscribe 解析成功
- **WHEN** domscribe 库可用且 HTML 有效
- **THEN** 系统返回 Markdown 内容
#### Scenario: domscribe 库未安装
- **WHEN** domscribe 库未安装
- **THEN** 系统尝试下一个解析器
### Requirement: markitdown 解析器
系统 SHALL 支持使用 markitdown 解析 HTML。
#### Scenario: markitdown 解析成功
- **WHEN** markitdown 库可用且 HTML 有效
- **THEN** 系统返回 Markdown 内容
#### Scenario: markitdown 库未安装
- **WHEN** markitdown 库未安装
- **THEN** 系统尝试下一个解析器
### Requirement: html2text 解析器
系统 SHALL 支持使用 html2text 解析 HTML兜底方案
#### Scenario: html2text 解析成功
- **WHEN** html2text 库可用且 HTML 有效
- **THEN** 系统返回 Markdown 内容
#### Scenario: html2text 库未安装
- **WHEN** html2text 库未安装
- **THEN** 系统返回失败信息
### Requirement: 下载器在 html 目录下
系统 SHALL 将下载器和清理器放在 html 目录下,不拆分。
#### Scenario: downloader.py 在 html 目录
- **WHEN** 使用 URL 下载功能
- **THEN** 从 readers/html/downloader.py 导入
#### Scenario: cleaner.py 在 html 目录
- **WHEN** 使用 HTML 清理功能
- **THEN** 从 readers/html/cleaner.py 导入
### Requirement: 每个 HTML 解析器独立文件
系统 SHALL 将每个 HTML 解析器实现为独立的单文件模块。
#### Scenario: trafilatura 解析器在独立文件
- **WHEN** 使用 trafilatura 解析器
- **THEN** 从 readers/html/trafilatura.py 导入
#### Scenario: domscribe 解析器在独立文件
- **WHEN** 使用 domscribe 解析器
- **THEN** 从 readers/html/domscribe.py 导入
#### Scenario: markitdown 解析器在独立文件
- **WHEN** 使用 markitdown 解析器
- **THEN** 从 readers/html/markitdown.py 导入
#### Scenario: html2text 解析器在独立文件
- **WHEN** 使用 html2text 解析器
- **THEN** 从 readers/html/html2text.py 导入