如何获取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
相关产品推荐
相关产品推荐

