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

如何用PyPDF2与ReportLab在长PDF每10行后动态插入数字文本

解决PDF每10行后插入数字的动态坐标问题

要实现每10行后精准插入数字,核心是获取每行文本的实际位置坐标,而非硬编码y值。原代码存在逻辑混乱(重复遍历页面、多次写入PDF)和坐标固定的问题,以下是修正后的可行方案:

核心思路

借助pdfplumber提取每行文本的边界框(bbox)信息,拿到第10行的实际位置参数,动态设置drawString的坐标,让数字精准插入到目标行末尾。

修正后的代码

import PyPDF2
import pdfplumber
import io
from reportlab.lib.pagesizes import A4
from reportlab.pdfgen import canvas

# 输入输出路径
input_pdf_path = r'C:\PyCharm Projects\AirRumi\pdfs\test.pdf'
output_pdf_path = r'C:\PyCharm Projects\AirRumi\pdfs\text.pdf'

pdf_writer = PyPDF2.PdfWriter()

# 同时用pdfplumber和PyPDF2处理,避免重复打开文件
with pdfplumber.open(input_pdf_path) as pdf, open(input_pdf_path, 'rb') as pdf_file:
    pdf_reader = PyPDF2.PdfReader(pdf_file)
    total_pages = len(pdf_reader.pages)
    
    for page_num in range(total_pages):
        pl_page = pdf.pages[page_num]
        py_page = pdf_reader.pages[page_num]
        
        # 提取每行的文本+位置信息,返回的列表元素是包含bbox的字典
        text_lines = pl_page.extract_text_lines()
        if not text_lines:  # 空页直接跳过处理
            pdf_writer.add_page(py_page)
            continue
        
        block_number = 10
        # 按每10行分组遍历
        for i in range(0, len(text_lines), 10):
            # 取当前组的最后一行,避免索引超出总行数
            end_line_idx = min(i + 9, len(text_lines)-1)
            end_line = text_lines[end_line_idx]
            
            # 从bbox中提取行的位置:(x0, y0, x1, y1)
            # x0=行左侧x坐标,y0=行底部y坐标,x1=行右侧x坐标,y1=行顶部y坐标
            line_bbox = end_line['bbox']
            # 设置插入位置:行右侧偏移10单位避免重叠,行顶部向下偏移2单位对齐
            insert_x = line_bbox[2] + 10
            insert_y = line_bbox[1] - 2
            
            # 创建临时PDF绘制数字
            packet = io.BytesIO()
            can = canvas.Canvas(packet, pagesize=A4)
            can.drawString(insert_x, insert_y, str(block_number))
            can.save()
            
            # 合并临时PDF到原页面
            packet.seek(0)
            new_pdf = PyPDF2.PdfReader(packet)
            py_page.merge_page(new_pdf.pages[0])
            
            block_number += 10
        
        # 将处理后的页面加入写入器
        pdf_writer.add_page(py_page)

# 一次性写入最终PDF
with open(output_pdf_path, 'wb') as output_file:
    pdf_writer.write(output_file)

关键细节说明

  1. 行位置获取:extract_text_lines()返回的每行数据自带bbox字段,通过这个字段能拿到文本行的精确位置,解决了硬编码坐标不匹配的问题。
  2. 动态坐标计算:通过给x、y坐标设置小偏移,确保插入的数字不会和原文本重叠,且对齐在目标行的末尾位置。
  3. 逻辑优化:避免重复打开PDF文件,统一用一个PdfWriter处理所有页面,最后一次性写入,既提升效率又避免文件覆盖问题。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.18 22:41:17