You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用Python+BeautifulSoup将img标签替换为对应OCR识别文本

Tika解析docx替换img为OCR文本实现方案

实现逻辑

  • 优先构建OCR内容映射表:遍历XML内所有name="resourceName"的<meta>标签,提取标签content属性存的图片文件名,同时找到该标签所属解析块内class="ocr"的div标签,提取识别到的文本,以键值对形式存入字典,后续替换直接查表即可,无需重复遍历DOM,效率更高
  • 处理img标签src前缀:Tika输出的img标签src值默认带embedded:前缀,匹配前需要先剥离该前缀,才能和映射表内的文件名精准匹配
  • 原位替换img节点:遍历正文所有<img>标签,匹配到对应OCR文本后,直接在原img标签的位置插入文本节点,保证文本顺序和原文档排版一致

可直接运行的代码示例

from bs4 import BeautifulSoup, NavigableString

# 读取Tika输出的XML内容,替换为你自己的文件读取/接口返回逻辑
with open("tika_result.xml", "r", encoding="utf-8") as f:
    tika_xml_content = f.read()

# 初始化BeautifulSoup对象,用xml解析器避免标签属性解析异常
soup = BeautifulSoup(tika_xml_content, "xml")

# 第一步:构建 图片文件名->OCR文本 的映射字典
ocr_content_map = {}
for resource_meta in soup.find_all("meta", attrs={"name": "resourceName"}):
    img_file_name = resource_meta.get("content")
    if not img_file_name:
        continue
    # meta标签的父节点即为单张图片对应的解析块
    img_parse_block = resource_meta.parent
    ocr_div = img_parse_block.find("div", attrs={"class": "ocr"})
    if ocr_div:
        # 提取OCR文本,可根据需求决定是否strip前后空白
        ocr_content_map[img_file_name] = ocr_div.get_text(strip=True)

# 第二步:遍历所有img标签做替换
for img_tag in soup.find_all("img"):
    img_src = img_tag.get("src", "")
    # 剥离embedded:前缀
    if img_src.startswith("embedded:"):
        real_file_name = img_src.split("embedded:", 1)[1]
        # 查到对应OCR内容就替换
        if real_file_name in ocr_content_map:
            img_tag.replace_with(NavigableString(ocr_content_map[real_file_name]))

# 最终提取处理完成的全文档文本
final_doc_text = soup.get_text()

适配说明

  • 如果你的Tika输出XML中,resourceName对应的meta标签和ocr div不在同一个直接父节点下,只需要调整img_parse_block的查找逻辑(比如改成找向上3层父节点)即可,核心匹配逻辑不需要改动
  • 常规docx经Tika解析生成的embedded前缀文件名都是唯一的,如果遇到重名图片导致匹配错误,可以给映射表的key补充上层路径等唯一标识做区分
  • 替换逻辑默认保留原文档的内容顺序,OCR文本会插入到原图片所在的正文位置,不需要额外做顺序调整

内容的提问来源于stack exchange,提问作者Tau n Ro

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.26 12:57:14