如何用Python实现类Bionic Reading的PDF文本加粗并保留原格式与图片?
实现PDF仿生阅读(Bionic Reading)效果:保留格式与图表的可行方案
针对你需要给PDF单词前几个字母加粗、同时完全保留原格式和图表的需求,pypdf和ReportLab确实无法满足——前者仅能提取/合并文本,无法精细化编辑页面元素;后者需要从头生成PDF,无法复用原文档的布局、字体和非文本元素。下面是基于**PyMuPDF(fitz)**的解决方案,它能直接操作PDF页面的文本块,完美保留原有格式、图片和图表。
核心思路
PyMuPDF允许直接访问PDF的页面对象,读取文本块的字体、大小、位置等属性,修改文本内容后再写回原页面,非文本元素(图片、表格、矢量图形)完全不受影响,适合处理科研论文这类对格式要求极高的文档。
步骤与代码实现
安装依赖
pip install pymupdf核心处理代码
import fitz # PyMuPDF def apply_bionic_reading(input_pdf, output_pdf, bold_char_count=2): # 打开原PDF doc = fitz.open(input_pdf) for page in doc: # 获取页面的结构化文本数据(包含字体、位置等信息) text_dict = page.get_text("dict") for block in text_dict["blocks"]: # 仅处理纯文本块(跳过图片、表格等非文本元素) if block["type"] != 0: continue for line in block["lines"]: processed_spans = [] for span in line["spans"]: original_text = span["text"] original_font = span["font"] font_size = span["size"] text_color = span["color"] # 尝试获取对应粗体字体(优先用原字体的粗体变体) bold_font = original_font.replace("Regular", "Bold") if "Regular" in original_font else f"{original_font}-Bold" # 若粗体字体不存在, fallback 到原字体并启用粗体标志 if not doc.has_font(bold_font): bold_font = original_font # 分割单词并处理每个单词的加粗部分 words = original_text.split() segments = [] for word in words: if len(word) <= bold_char_count: # 短单词直接全加粗 segments.append((word, bold_font, True)) else: # 前N个字符加粗,剩余部分保留原格式 segments.append((word[:bold_char_count], bold_font, True)) segments.append((word[bold_char_count:], original_font, False)) segments.append((" ", original_font, False)) # 还原单词间的空格 # 合并同字体的连续文本段,减少不必要的span拆分 current_font = None current_text = "" current_is_bold = False for seg_text, seg_font, seg_bold in segments: if seg_font == current_font and seg_bold == current_is_bold: current_text += seg_text else: if current_text: processed_spans.append({ "text": current_text, "font": current_font, "size": font_size, "color": text_color, "flags": 1 if current_is_bold else 0 # 1代表粗体标志 }) current_font = seg_font current_text = seg_text current_is_bold = seg_bold # 添加最后一段文本 if current_text: processed_spans.append({ "text": current_text, "font": current_font, "size": font_size, "color": text_color, "flags": 1 if current_is_bold else 0 }) # 替换原行的span数据 line["spans"] = processed_spans # 将修改后的文本数据写回页面 page.set_text("dict", text_dict) # 保存处理后的PDF doc.save(output_pdf) doc.close() # 使用示例:处理input.pdf,生成带仿生阅读效果的output.pdf,每个单词前2个字母加粗 apply_bionic_reading("input.pdf", "output_bionic.pdf", bold_char_count=2)
关键注意事项
- 字体兼容性:部分PDF使用的字体可能没有官方粗体变体,代码中通过启用
flags=1让阅读器强制显示粗体,大部分主流阅读器(Adobe Acrobat、Chrome、Foxit)都支持此设置。 - 格式保留:所有文本的位置、行距、段落缩进、字体大小完全与原文档一致,图片、表格、公式等非文本元素不会被修改或删除。
- 科研论文适配:对于公式(通常为矢量图形),PyMuPDF不会识别为文本块,因此不会被修改,不影响公式的阅读。
- 性能优化:仅修改文本块内容,无需重新渲染整个页面,处理大篇幅科研论文的速度远快于从头生成PDF的方案。
内容的提问来源于stack exchange,提问作者Jacob Henderson
相关产品推荐
相关产品推荐

