如何加速从PDF提取文本的Python函数 批量处理数万份法院判决PDF
首先澄清几个认知误区
- 你对numba的猜测完全正确:numba的
@njit装饰器只支持纯Python数值运算和极少量内置操作,你调用的wget、pdftotext、文件IO都不在它的支持范围内,这类工具本来就是为数值计算场景设计的,完全不适合当前任务,直接放弃这个方向即可。 - 你理解的「向量化加速」适用场景错了:Pandas/Numpy的向量化是为了规避Python循环的开销,加速纯内存CPU密集型的数值计算,而你的任务90%以上的耗时都在**网络下载PDF(网络IO)、磁盘读写文件(磁盘IO)**上,这部分瓶颈根本不是Python循环的开销,所以再怎么折腾向量化也不会有效果。
- 你之前直接传Series给
Link2Text报错的原因很简单:这个函数本身只接受单个URL字符串作为输入,你传一整个Series进去,wget根本没法处理序列输入,自然报错。df['URLs'].item是方法,你没加括号调用,所以传了个函数对象进去才会报decode的错,就算你加了括号,.item()也只能取单个元素,还是处理不了批量URL。
正确的优化方案:用并发处理IO密集型任务
IO密集型任务的核心优化逻辑是:不让CPU在等待网络/磁盘响应的时候闲置,同时发起多个下载、解析请求,就能大幅提升整体速度。这里推荐用concurrent.futures.ThreadPoolExecutor多线程实现,代码改动极小,速度能提升数倍到数十倍(取决于你的网络带宽)。
优化后代码示例
import os import pandas as pd import pdftotext import wget import threading from concurrent.futures import ThreadPoolExecutor # 原函数仅需调整临时文件名,避免多线程写入冲突 def Link2Text(Link): # 用线程ID生成唯一临时文件名,不会和其他线程冲突 temp_file = f"Temporary_Opinion_{threading.get_ident()}.pdf" OpinionPDF = wget.download(Link, temp_file) with open(OpinionPDF, "rb") as f: pdf = pdftotext.PDF(f) OpinionText = "\n\n".join(pdf) if os.path.exists(temp_file): os.remove(temp_file) return OpinionText # 你的示例数据 df = pd.DataFrame({'OpinionText': [""], 'URLs': ["https://cases.justia.com/federal/appellate-courts/ca6/20-6226/20-6226-2021-09-17.pdf?ts=1631908842"]}) df = pd.concat([df]*50, ignore_index=True) # 多线程调用,max_workers可根据你的网络情况调整,一般设为10-30即可 max_workers = 20 with ThreadPoolExecutor(max_workers=max_workers) as executor: df['OpinionText'] = list(executor.map(Link2Text, df['URLs'].tolist()))
额外优化提示
- 可以把max_workers调整到你网络能承受的上限,带宽足够的话设为50也可以,速度会更快。
- 处理数万份PDF时建议加失败重试机制,避免因为个别网络请求失败导致整个任务中断。
内容的提问来源于stack exchange,提问作者bbernicker
相关产品推荐
相关产品推荐

