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

如何获取PDF特定文本的字体名?PyMuPDF实现及替代方案问询

如何在PyMuPDF中获取特定文本的字体名并用于条件判断?

问题背景

你现有基于PyMuPDF提取PDF内容的脚本,希望给txt变量添加基于字体名的条件判断(比如判断是否为Cambria-Bold),但发现page.get_fonts()只能获取页面所有字体,无法关联到特定文本块。

原有核心代码:

for page in doc:
    rect = fitz.Rect(22, 52, 562,802)  # 裁剪页面边距,忽略页眉、页脚和左侧内容
    blocks = page.get_text("blocks",rect, flags=fitz.TEXTFLAGS_TEXT)

    for i in blocks:
        if (i[-3][0].isdigit()):# 判断是否为标题
            if (i[-3].partition(" ")[0].count('.')==0):# 判断是否为子标题
                nr=i[-3].partition(" ")[0]
                txt = (i[-3]).partition(" ")[2]
            else:
                sub_nr='="' +i[-3].partition(" ")[0]+ '"'
                sub_txt=i[-3].partition(" ")[2]

        elif (i[-3].startswith("[V2G")):
            id=i[-3].partition("\n")[0].replace("[", " ").replace("]"," ")
            text=i[-3].partition("\n")[2].strip()
            data.append(req(filename, nr, txt, sub_nr, sub_txt, id, text))

PyMuPDF的解决方案:使用"dict"文本提取模式

page.get_text("blocks")模式不会返回字体信息,你需要改用"dict"模式,该模式会返回包含**文本块(blocks)、行(lines)、文本段(spans)**的层级结构,每个span对象包含对应文本的字体名、字号等属性。

修改后的代码示例:

for page in doc:
    rect = fitz.Rect(22, 52, 562,802)
    # 使用dict模式提取带格式的文本
    text_dict = page.get_text("dict", clip=rect, flags=fitz.TEXTFLAGS_TEXT)
    
    nr = ""
    txt = ""
    sub_nr = ""
    sub_txt = ""
    
    for block in text_dict["blocks"]:
        if "lines" not in block:
            continue  # 跳过非文本块
        for line in block["lines"]:
            for span in line["spans"]:
                text = span["text"].strip()
                font_name = span["font"]  # 获取当前文本段的字体名
                
                if not text:
                    continue
                
                # 判断是否为标题类文本
                if text[0].isdigit():
                    if text.partition(" ")[0].count('.') == 0:
                        # 主标题,判断字体是否为Cambria-Bold
                        if font_name == "Cambria-Bold":
                            nr = text.partition(" ")[0]
                            txt = text.partition(" ")[2]
                    else:
                        sub_nr = f'"{text.partition(" ")[0]}"'
                        sub_txt = text.partition(" ")[2]
                
                elif text.startswith("[V2G"):
                    id_part = text.partition("\n")[0].replace("[", " ").replace("]", " ")
                    content = text.partition("\n")[2].strip()
                    data.append(req(filename, nr, txt, sub_nr, sub_txt, id_part, content))

关键说明:

  • span["font"]返回的是PDF中实际的字体名称,可能和你预期的名称略有差异(比如可能显示为Cambria-BoldMT而不是Cambria-Bold),建议先打印所有font_name值确认实际名称。
  • 层级结构:text_dict["blocks"] → 每个block包含lines → 每个line包含多个spans(同一行中不同格式的文本段)。

替代Python库选项

如果PyMuPDF的方式不符合需求,还可以尝试以下库:

  • pdfplumber:对文本格式的提取更直观,每个字符/文本段都携带字体信息:
import pdfplumber

with pdfplumber.open("your_file.pdf") as pdf:
    page = pdf.pages[0]
    # 裁剪页面
    cropped_page = page.crop((22, 52, 562, 802))
    for word in cropped_page.extract_words():
        text = word["text"]
        font_name = word["fontname"]
        # 这里可以添加你的条件判断逻辑
        if font_name == "Cambria-Bold" and text[0].isdigit():
            # 处理标题逻辑
            pass
  • pdfminer.six:是PDF解析的底层库,能精细控制文本和字体的关联,但使用复杂度更高。需要遍历PDF的文本对象,通过LTTextLine、LTChar等对象获取字体信息,每个LTChar包含对应的字体名。

内容的提问来源于stack exchange,提问作者user34088

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.26 02:25:39