使用Python 3.10.6+Camelot读取PDF特定表格时崩溃求助
使用Camelot读取Word生成的PDF表格时遇到解密错误(PDF未加密)
问题详情
- Python版本:3.10.6
- 需求:读取PDF中第24、26页的表格,仅成功读取第21-23页和第25页的表格
- 表格差异:无法读取的表格第二行为单列,可读取的表格第二行为多列
- 核心报错:
ValueError: Data must be padded to 16 byte boundary in CBC mode,但确认PDF未设置加密 - PDF来源:由Microsoft Office Professional Plus 2019的Word生成
所用代码
tables = camelot.read_pdf( cFile, pages=str(24), password=None, flavor='lattice', flag_size=True, strip_text='\n' # 已尝试的注释参数均无效: # , backend='poppler' # , process_background=True # , table_areas=['36,731,576,396'] # , table_regions=['36,731,576,396'] # , edge_tol=200 # , row_tol=10 # , line_scale=40 # , shift_text=['r', 'b'] # , copy_text=['h'] )
完整报错信息
Traceback (most recent call last): File "G:\My Drive\Bugs\15888 - Convert PDF table data to Oracle data\Test Table 9.py", line 58, in <module> tables = camelot.read_pdf( cFile File "C:\Users\56663\AppData\Roaming\Python\Python310\site-packages\camelot\io.py", line 113, in read_pdf tables = p.parse( File "C:\Users\56663\AppData\Roaming\Python\Python310\site-packages\camelot\handlers.py", line 172, in parse self._save_page(self.filepath, p, tempdir) File "C:\Users\56663\AppData\Roaming\Python\Python310\site-packages\camelot\handlers.py", line 120, in _save_page outfile.write(f) File "C:\Users\56663\AppData\Roaming\Python\Python310\site-packages\PyPDF2\_writer.py", line 839, in write self.write_stream(stream) File "C:\Users\56663\AppData\Roaming\Python\Python310\site-packages\PyPDF2\_writer.py", line 812, in write_stream self._sweep_indirect_references(self._root) File "C:\Users\56663\AppData\Roaming\Python\Python310\site-packages\PyPDF2\_writer.py", line 961, in _sweep_indirect_references data = self._resolve_indirect_object(data) File "C:\Users\56663\AppData\Roaming\Python\Python310\site-packages\PyPDF2\_writer.py", line 1006, in _resolve_indirect_object real_obj = data.pdf.get_object(data) File "C:\Users\56663\AppData\Roaming\Python\Python310\site-packages\PyPDF2\_reader.py", line 1160, in get_object retval = self._encryption.decrypt_object( File "C:\Users\56663\AppData\Roaming\Python\Python310\site-packages\PyPDF2\_encryption.py", line 744, in decrypt_object return cf.decrypt_object(obj) File "C:\Users\56663\AppData\Roaming\Python\Python310\site-packages\PyPDF2\_encryption.py", line 185, in decrypt_object obj[dictkey] = self.decrypt_object(value) File "C:\Users\56663\AppData\Roaming\Python\Python310\site-packages\PyPDF2\_encryption.py", line 179, in decrypt_object data = self.strCrypt.decrypt(obj.original_bytes) File "C:\Users\56663\AppData\Roaming\Python\Python310\site-packages\PyPDF2\_encryption.py", line 87, in decrypt d = aes.decrypt(data) File "C:\Users\56663\AppData\Roaming\Python\Python310\site-packages\Crypto\Cipher\_mode_cbc.py", line 246, in decrypt raise ValueError("Data must be padded to %d byte boundary in CBC mode" % self.block_size) ValueError: Data must be padded to 16 byte boundary in CBC mode
解决方案建议
- 修复PDF结构:用Adobe Acrobat或其他专业PDF工具打开原文件,选择「另存为」重新生成PDF,修复Word导出时可能产生的字节对齐异常。
- 强制使用Poppler后端:确保已安装Poppler(Windows需将其路径添加到系统环境变量),然后在代码中启用
backend='poppler'参数,跳过PyPDF2的解密逻辑。 - 提前提取目标页面:先用PyPDF2提取第24、26页到临时PDF,再用Camelot读取临时文件:
from PyPDF2 import PdfReader, PdfWriter # 提取目标页面到临时文件 reader = PdfReader(cFile) writer = PdfWriter() for page_idx in [23,25]: # PyPDF2页面索引从0开始 writer.add_page(reader.pages[page_idx]) temp_pdf = "temp_target_pages.pdf" with open(temp_pdf, "wb") as f: writer.write(f) # 读取临时PDF的表格 tables = camelot.read_pdf( temp_pdf, pages="1,2", flavor='lattice', flag_size=True, strip_text='\n' ) - 切换到Stream模式:对结构特殊的表格,尝试
flavor='stream',配合table_areas参数精确定位表格区域。 - 升级依赖库:更新PyPDF2、Camelot及加密相关库到最新版本,修复已知bug:
pip install --upgrade pypdf2 camelot-py[base] pycryptodome
内容的提问来源于stack exchange,提问作者Gary Crockett
相关产品推荐
相关产品推荐

