处理 Markdown 转换过程中损坏的 PDF 文件
本文讨论了在使用 Python 和 markitdown
库将 PDF 文件转换为 Markdown 时遇到的常见问题,即遇到损坏或无效的 PDF 文件。我们将探讨问题、原因,并提供包含代码示例的强大解决方案。
问题:
在处理大量文件(尤其是 PDF 文件)时,您可能会遇到损坏、不完整或无效的 PDF 文档。尝试使用 pdfminer
等库(markitdown
依赖于它)转换这些文件将导致错误,从而停止转换过程,并可能导致脚本崩溃。常见的错误消息是 pdfminer.psexceptions.PSEOF: Unexpected EOF
,表示 PDF 解析器意外到达文件末尾。
原因:
- 下载不完整: PDF 文件可能只是部分下载或在传输过程中损坏。
- 文件损坏: PDF 文件可能由于存储问题或其他不可预见的情况而损坏。
- PDF 格式无效: 即使文件扩展名为
.pdf
,该文件也可能不符合 PDF 规范。 - 软件问题: 用于创建 PDF 的软件可能引入了错误。
解决方案:
关键是实施错误处理和验证,以优雅地跳过有问题的文件,并继续处理其余文件。以下是解决方案的详细信息:
-
PDF 验证: 在尝试转换 PDF 之前,我们将实现一个函数来检查它是否是有效的 PDF。此函数将尝试使用
pdfminer
解析 PDF。如果解析失败,我们则认为 PDF 无效。from pdfminer.pdfparser import PDFParser from pdfminer.pdfdocument import PDFDocument def is_valid_pdf(filepath): try: with open(filepath, 'rb') as f: parser = PDFParser(f) doc = PDFDocument(parser) # 尝试创建文档 return True except Exception: # 任何异常都意味着它可能无效 return False
-
将验证集成到文件处理函数中: 我们将修改
find_ppt_and_pdf
函数以使用is_valid_pdf
函数。import os from markitdown import MarkItDown def find_ppt_and_pdf(directory): # ... (函数其余部分) for file in files: if file.endswith((".ppt", ".pptx", ".pdf")): full_path = os.path.join(root, file) if file.endswith(".pdf"): if not is_valid_pdf(full_path): print(f"跳过无效的 PDF:{full_path}") continue # 跳到下一个文件 # ... (文件处理代码的其余部分,包括有问题的文件的跳过)
-
处理转换过程中的异常: 我们将使用
try-except
块来捕获markitdown
转换过程中的异常。这使我们能够处理错误而不会使脚本崩溃。try: md = MarkItDown() result = md.convert(full_path) # ... except Exception as e: print(f"处理 {full_path} 时出错:{e}") continue # 跳到下一个文件
-
解决有问题的文件的跳过: 由于路径分隔符不一致,原始代码尝试跳过特定文件存在缺陷。我们使用
os.path.normpath()
在比较之前对路径进行规范化,从而确保跨操作系统的一致行为。problematic_file = os.path.normpath('../../code/tensorflow-b2.4.0/bazelcache/bazel/_bazel_root/39de0dbcfb68c8735bd088c62fa061a4/external/snappy/testdata/paper-100k.pdf') if os.path.normpath(full_path) == problematic_file: print(f"跳过有问题的的文件:{full_path}") continue
完整代码:
import os
from markitdown import MarkItDown
from pdfminer.pdfparser import PDFParser
from pdfminer.pdfdocument import PDFDocument
def is_valid_pdf(filepath):
# ... (上面定义的函数)
def find_ppt_and_pdf(directory):
# ... (上面定义的函数,包含所有更改)
if __name__ == "__main__":
# ... (主执行块)
结论:
通过实施这些更改,您的脚本在处理潜在的 PDF 文件时将更加强大。验证步骤确保仅处理有效的 PDF,并且异常处理可防止错误导致转换过程停止。规范化的路径比较确保可以可靠地跳过特定文件。此方法使您可以有效地转换大量文件,即使其中一些文件已损坏或无效。