Skip to content

信息提取工具 ​

本文引用的源码文件

本文引用的文件

目录 ​

  1. 引言
  2. 项目结构
  3. 核心组件
  4. 架构总览
  5. 详细组件分析
  6. 依赖关系分析
  7. 性能与优化建议
  8. 故障排查指南
  9. 结论

引言 ​

本文件面向“信息提取工具”的技术文档,聚焦网页内容读取、结构化数据解析、表单与链接收集、元数据与结构化数据抽取、Shadow DOM 穿透以及搜索高亮等能力。该工具以 Chrome 扩展 Content Script 为核心运行环境,通过统一的 message 路由暴露给 background 侧工具调用,最终形成可扩展的信息提取管线。

项目结构 ​

信息提取相关代码主要位于 content 层:

  • page-extract.js:元数据、链接、表单、图片、Markdown/JSON 转换、iframe 内容、页面搜索。
  • shadow-dom-utils.js:Shadow DOM 与 iframe 的深度查询、文本/HTML 获取、选择范围处理。
  • page-tools.js:纯文本/富文本获取、表格提取、剪贴板、悬停、文本高亮等基础工具。
  • index.js:Content Script 入口,统一消息路由,将上层工具映射到具体实现。
  • browser-tools.js:background 侧对外暴露的工具定义(如 page_content、extract_data、search_in_page、iframe_content)。
graph TB
subgraph "Background 工具"
BT["browser-tools.js<br/>工具定义"]
end
subgraph "Content Script"
CI["index.js<br/>消息路由"]
PT["page-tools.js<br/>基础工具"]
PE["page-extract.js<br/>提取逻辑"]
SDU["shadow-dom-utils.js<br/>Shadow DOM/iframe 穿透"]
end
BT --> CI
CI --> PT
CI --> PE
PE --> SDU
PT --> SDU

图表来源

章节来源

核心组件 ​

  • 纯文本与富文本获取
    • 纯文本:基于 Shadow DOM 穿透的 deepGetText,支持 iframe 同源内容合并。
    • 富文本:基于 deepGetHtml 获取完整 HTML,可剥离样式;选区富文本通过 Range 克隆节点生成。
  • 表格数据解析
    • 单表提取:extractTable 支持 JSON/Markdown 输出,可选是否包含表头行。
    • 多表结构化:pageToJson 批量提取多个 table、ul/ol 列表、JSON-LD、article、Microdata。
  • 链接与表单
    • 链接:extractLinks 支持内/外链过滤、可选图片链接纳入。
    • 表单:extractForms 识别 input/textarea/select,记录 name/id/type/placeholder/required/selector。
  • 元数据与结构化数据
    • 元数据:extractMetadata 提取 title/description/keywords/author、Open Graph、Twitter Card、canonical、JSON-LD、Microdata。
  • Shadow DOM 穿透
    • 深度查询、文本/HTML 获取、选择范围、视口坐标计算、监听器管理。
  • 页面搜索与高亮
    • searchInPage 支持 plain/regex 模式、大小写敏感、上下文片段、结果高亮。

章节来源

架构总览 ​

信息提取在 MV3 双进程架构中的调用路径如下:

  • Background 工具定义 extract_data、page_content、search_in_page、iframe_content 等。
  • Background 通过 chrome.runtime 向 Content Script 发送消息。
  • Content Script 的 index.js 根据 message.type 分发到对应处理器。
  • 处理器调用 page-extract.js 或 page-tools.js 的具体函数。
  • 底层依赖 shadow-dom-utils.js 完成跨 Shadow DOM/iframe 的访问。
sequenceDiagram
participant BG as "Background<br/>browser-tools.js"
participant CS as "Content Script<br/>index.js"
participant EX as "page-extract.js"
participant PT as "page-tools.js"
participant SDU as "shadow-dom-utils.js"
BG->>CS : 发送消息 {type, params}
CS->>CS : 查找 HANDLERS[type]
alt 类型=EXTRACT_METADATA/EXTRACT_LINKS/EXTRACT_FORMS/EXTRACT_IMAGES/SEARCH_IN_PAGE/IFRAME_CONTENT
CS->>EX : 调用对应提取函数
EX->>SDU : deepQuerySelector/deepGetText/deepGetHtml
SDU-->>EX : 返回元素/文本/HTML
EX-->>CS : 返回结构化结果
else 类型=GET_PAGE_TEXT/GET_FULL_HTML/EXTRACT_TABLE
CS->>PT : 调用基础工具
PT->>SDU : 使用 Shadow DOM 穿透
SDU-->>PT : 返回内容
PT-->>CS : 返回结果
end
CS-->>BG : sendResponse(结果)

图表来源

详细组件分析 ​

纯文本与富文本获取 ​

  • 纯文本
    • 通过 getPageText 调用 deepGetText,自动合并 Shadow DOM 与同源 iframe 文本,并截取最大长度。
    • 可选择包含标题和链接摘要,便于快速概览。
  • 富文本
    • getFullHtml 基于 deepGetHtml 获取完整 HTML,可按需移除 style 属性以减少体积。
    • getSelectedContent 支持 text/html 两种格式,html 模式下通过 Range.cloneContents 保留富文本结构。
flowchart TD
Start(["调用 getPageText/getFullHtml"]) --> Mode{"格式?"}
Mode --> |text| GetText["deepGetText()"]
Mode --> |html| GetHtml["deepGetHtml()"]
GetText --> Clean["截断 maxLength / 统计词数"]
GetHtml --> StripStyle{"是否去除样式?"}
StripStyle --> |是| RemoveStyle["移除 style 属性"]
StripStyle --> |否| KeepStyle["保留样式"]
Clean --> Return["返回结构化结果"]
RemoveStyle --> Return
KeepStyle --> Return

图表来源

章节来源

表格数据解析 ​

  • 单表提取 extractTable
    • 支持 selector 定位表格,遍历 tr/td/th 提取单元格文本。
    • 支持 includeHeaders 控制是否包含首行作为表头。
    • 输出格式:json(含 data、rowCount、columnCount)或 markdown(标准表格语法)。
  • 多表结构化 pageToJson
    • 批量扫描 root 下的 table、ul/ol、JSON-LD、article、Microdata。
    • 对每个 table 提取 headers 与 rows,限制 maxItems 避免过大结果。
    • 对 Microdata 去重(按 itemType + 前缀文本签名),避免重复条目。
flowchart TD
TStart(["extractTable/pageToJson"]) --> Locate["定位表格/根节点"]
Locate --> Rows["遍历 tr 行"]
Rows --> Cells["遍历 td/th 单元格"]
Cells --> BuildRow["构建行数据"]
BuildRow --> Format{"输出格式?"}
Format --> |json| JsonOut["JSON: data/rowCount/columnCount"]
Format --> |markdown| MdOut["Markdown: 表头+分隔符+数据行"]
JsonOut --> TReturn["返回结果"]
MdOut --> TReturn

图表来源

章节来源

链接与表单提取 ​

  • 链接 extractLinks
    • 遍历 a[href],过滤 javascript:/# 协议,判断内外域。
    • 可选 includeImages 将 img[src] 作为 type=image 的链接项加入。
  • 表单 extractForms
    • 支持 formSelector 限定单个表单,否则遍历所有 form。
    • 字段类型:input/textarea/select,记录 name/id/type/placeholder/required/selector。
    • select 额外收集 options[value,text]。
flowchart TD
LStart(["extractLinks/extractForms"]) --> Type{"类型?"}
Type --> |links| ScanA["遍历 a[href]"]
Type --> |forms| ScanF["遍历 form/input/textarea/select"]
ScanA --> Filter["过滤协议/内外域"]
ScanF --> Fields["收集字段属性"]
Filter --> LReturn["返回 links 数组"]
Fields --> FReturn["返回 forms 数组"]

图表来源

章节来源

元数据与结构化数据 ​

  • 元数据 extractMetadata
    • 标题、描述、关键词、作者。
    • Open Graph:og:title/description/image/url/type/site_name/locale。
    • Twitter Card:card/title/description/image/site/creator。
    • Canonical URL。
    • JSON-LD:解析 script[type="application/ld+json"],兼容 @graph 数组。
    • Microdata:itemscope/itemprop 递归收集,避免嵌套 itemscope 重复。
  • 结构化 JSON pageToJson
    • 同时提取 tables/lists/jsonLd/articles/microdata,并给出 counts。
classDiagram
class MetadataExtractor {
+extractMetadata() Object
+pageToJson(selector, maxItems) Object
}
class JSONLDParser {
+parseScripts() Array
}
class MicrodataCollector {
+collectItemscope() Array
}
MetadataExtractor --> JSONLDParser : "解析 ld+json"
MetadataExtractor --> MicrodataCollector : "收集 itemscope"

图表来源

章节来源

Shadow DOM 穿透技术 ​

  • 深度查询
    • deepQuerySelector/deepQuerySelectorAll 优先遍历 shadowRoot 与 iframe,再回退到当前 root 的 query。
    • 支持 maxDepth 防止无限递归,visited 集合防止循环引用。
  • 文本/HTML 获取
    • deepGetText 合并 body.innerText 与 shadow tree textContent,拼接 iframe 内容。
    • deepGetHtml 合并 documentElement.outerHTML 与 shadow innerHTML,插入注释标记区分来源。
  • 选择范围与视口坐标
    • deepGetSelection 递归查找有焦点 frame 的选择范围。
    • getElementViewportPosition/getRangeViewportPosition 累加 iframe 偏移,确保坐标正确。
  • 监听器管理
    • attachSelectionListeners/removeSelectionListeners 为各 Shadow Root 注册 selectionchange。
flowchart TD
SStart(["Shadow DOM 操作"]) --> Traverse["遍历 * 元素"]
Traverse --> CheckSR{"存在 shadowRoot?"}
CheckSR --> |是| RecurseSR["递归进入 shadowRoot"]
CheckSR --> |否| CheckIF{"存在 iframe/frame?"}
CheckIF --> |是| RecurseIF["递归进入 iframeDoc"]
CheckIF --> |否| QueryCurrent["在当前 root 执行 query"]
RecurseSR --> Merge["合并结果"]
RecurseIF --> Merge
QueryCurrent --> Merge
Merge --> SReturn["返回元素/文本/HTML/坐标"]

图表来源

章节来源

页面搜索与高亮 ​

  • searchInPage
    • plain 模式:使用 window.find 辅助定位,TreeWalker 遍历文本节点匹配正则。
    • regex 模式:直接对 body.innerText 执行正则匹配,支持大小写敏感。
    • 支持 contextLength 提供命中前后上下文,maxResults 限制结果数量。
    • highlight=true 时,通过 Range 包裹命中文本节点,避免替换 innerHTML 导致事件丢失。
flowchart TD
SearchStart(["searchInPage"]) --> Validate{"query/pattern 是否存在?"}
Validate --> |否| Error["返回错误:缺少关键词"]
Validate --> |是| Mode{"mode?"}
Mode --> |plain| Plain["window.find + TreeWalker 匹配"]
Mode --> |regex| Regex["RegExp.exec(bodyText)"]
Plain --> Context["构造上下文片段"]
Regex --> Context
Context --> Highlight{"highlight?"}
Highlight --> |是| WrapRange["Range 包裹命中文本节点"]
Highlight --> |否| SkipHighlight["跳过高亮"]
WrapRange --> Return["返回 matches/highlighted"]
SkipHighlight --> Return

图表来源

章节来源

iframe 内容获取 ​

  • getIframeContent
    • 遍历指定 selector 的 iframe,尝试访问 contentDocument/contentWindow.document。
    • 若同源且可访问,则读取 title、textContent、htmlLength。
    • 支持 includeNested 递归处理嵌套 iframe(默认深度限制为 2)。
    • 不可访问时仍返回基本信息(url、accessible=false)。
sequenceDiagram
participant Caller as "调用方"
participant API as "getIframeContent"
participant IF as "iframe 元素"
participant Doc as "iframe.contentDocument"
Caller->>API : 传入 selector/includeNested/maxLength
API->>IF : querySelectorAll(selector)
loop 每个 iframe
API->>Doc : 尝试访问 contentDocument
alt 可访问
Doc-->>API : title/textContent/htmlLength
API->>API : 递归处理嵌套 iframe
else 不可访问
Doc-->>API : 抛出异常
API->>API : accessible=false
end
end
API-->>Caller : 返回 iframes 列表与统计

图表来源

章节来源

依赖关系分析 ​

  • Content Script 入口 index.js 维护 HANDLERS Map,O(1) 查找消息处理器。
  • TOP_FRAME_ONLY_TYPES 确保某些工具只在顶层 frame 响应,避免 iframe 抢先应答。
  • ASYNC_HANDLERS 标记异步处理器,保持消息通道开放直到 Promise resolve。
  • 工具定义在 browser-tools.js,明确 dataType、format、filterType 等参数契约。
graph LR
BT["browser-tools.js<br/>工具定义"] --> CI["index.js<br/>HANDLERS/TOP_FRAME_ONLY_TYPES/ASYNC_HANDLERS"]
CI --> PT["page-tools.js"]
CI --> PE["page-extract.js"]
PT --> SDU["shadow-dom-utils.js"]
PE --> SDU

图表来源

章节来源

性能与优化建议 ​

  • 控制结果规模
    • 使用 maxItems/maxResults/maxLength 限制返回体量,避免大页面导致内存与传输压力。
  • 减少 DOM 遍历开销
    • 优先使用具体 selector 缩小范围,避免全页遍历。
    • 对 Shadow DOM/iframe 设置合理 maxDepth,避免深层树遍历。
  • 避免重复工作
    • 使用 seenUrls/seenJsonLd/seenMicrodata 去重,减少冗余解析。
  • 安全与稳定性
    • 对跨域 iframe 捕获异常并跳过,保证主流程稳定。
    • 高亮采用 Range 包裹文本节点,不替换 innerHTML,避免事件丢失与布局抖动。
  • 输出格式选择
    • 表格输出优先 JSON 用于程序处理,Markdown 用于人类阅读;按需选择。

[本节为通用指导,不直接分析具体文件]

故障排查指南 ​

  • 未找到目标元素
    • 检查 selector 是否正确,必要时使用 generateUniqueSelector 生成稳定选择器。
    • 确认是否在顶层 frame 调用需要 TOP_FRAME_ONLY_TYPES 的工具。
  • 跨域 iframe 不可访问
    • getIframeContent 会返回 accessible=false,这是预期行为;仅同源 iframe 可读取内容。
  • 搜索无结果
    • 确认 query/pattern 非空,plain/regex 模式差异;注意大小写敏感选项。
  • 高亮无效
    • 确保 highlight=true 且存在匹配;Range 高亮不会破坏事件监听。
  • 表单字段缺失
    • 确认字段为 input/textarea/select;动态生成的字段需在渲染后再次提取。

章节来源

结论 ​

信息提取工具以 Content Script 为中心,结合 Shadow DOM 穿透与 iframe 同源访问,提供了从纯文本、富文本到结构化数据的完整提取能力。通过统一的 message 路由与清晰的工具定义,扩展端与后台进程协作顺畅。建议在大规模页面中严格控制结果规模、合理使用 selector 与深度限制,并遵循安全最佳实践以避免跨域与事件丢失问题。

[本节为总结性内容,不直接分析具体文件]