根据原件实际结构编写自己的脚本,保留物理页码、原文、单位和来源。下面的库用法是示例;全页提取和实际读取是 Skill 的要求,方法和分批方式由你决定。
先取得每份 PDF 的总页数,覆盖物理页 1~N,逐页提取并保存内容。一个 PDF 中可能接着装订另一台风机的报告;通过封面、报告编号、使用编号、页眉和内部页码变化识别各份报告边界,记录它们的原始物理页范围,不用文件数量推断报告数量。
有完整文本层的页面,保存并读取全文;read_file 返回内容被截断时继续分页读取。无文本层或主体仍是扫描图的页面,渲染后逐页 read_file 看图,将实际读到的文字、表格数据、单位和图注保存到逐页记录中;细节不清楚时放大或裁切回看。扫描件全文文本搜索无命中不代表其图片中没有目标风机。
覆盖清单至少区分待读、已读和无法识别;生成文本或图片时先记为待读,完成实际读取并保存识别记录后才更新为已读。可分批读取并持续保存清单,不能因读取批次数或预览长度而跳过尾页。全部页面已读、各份报告身份和页范围已核对后,再开始比较和形成结论。确实无法识别时记录具体页码与限制,返回受限结果,不把它表述为资料未提供。
from pathlib import Path
import json
import pypdfium2 as pdfium
source = Path('uploads/实际原件.pdf')
output = Path('derived/pages')
output.mkdir(parents=True, exist_ok=True)
page_index = []
with pdfium.PdfDocument(source) as document:
total_pages = len(document)
for index in range(total_pages):
page = document[index]
try:
text_page = page.get_textpage()
try:
text = text_page.get_text_range()
finally:
text_page.close()
text_path = output / f'page-{index + 1}.txt'
text_path.write_text(text, encoding='utf-8')
entry = {'page': index + 1, 'text_path': str(text_path),
'text_chars': len(text), 'reading_status': 'pending'}
# 这里预渲染无文本页;有水印但主体是扫描图的页面也须补充渲染。
if not text.strip():
bitmap = page.render(scale=1.5)
image = bitmap.to_pil()
image_path = output / f'page-{index + 1}.png'
image.save(image_path)
entry['image_path'] = str(image_path)
image.close()
bitmap.close()
page_index.append(entry)
finally:
page.close()
(output / 'index.json').write_text(json.dumps(
{'source': str(source), 'total_pages': total_pages, 'pages': page_index},
ensure_ascii=False, indent=2), encoding='utf-8')
这个脚本只完成预处理,所有页仍为待读。接下来必须读取各页完整文本或图片、保存识别内容并更新状态;不能直接拿生成的清单声明“已读完全文”。分析前核对已读物理页集合等于 1~total_pages,并随报告交付覆盖记录。若后来发现漏页或报告边界变化,补读并更新提取事实后再分析。
render(scale=1.5) 将 PDF 点数放大1.5倍;小字或表格可选择更大 scale。不要一次渲染许多高分辨率页面导致内存或输出超限。部分页面有水印文字但主体仍是扫描图,需要根据文本内容和原页判断,不能仅用 text.strip() 做最终路由。
通过 read_file 查看 /workspace/derived/pages/page-N.png。若只是某一列看不清,用 Pillow 在脚本中裁切已生成的页面,再 read_file 查看裁切图。物理页码始终引用原 PDF 的 index+1,不用截取文件的排序冒充原页。
from PIL import Image
with Image.open('derived/pages/page-3.png') as image:
crop = image.crop((left, top, right, bottom)) # 坐标来自实际查看的图片
crop.save('derived/page-3-table.png')
扫描原件由主 Agent 直接读取页面图,然后将实际所见事实写入自己的提取/计算脚本或 JSON。原文不清楚就放大回看,不从预计结论推数字;没有看图能力时明确说明限制。
图表可自行用字符串生成 SVG、用 Pillow 绘制,或输出 CSV。所有用于交付的图表、事实和报告都在 run_python 的 output_paths 中声明,保留成功执行凭据。