按照文本内容将PDF文件拆分为单独的文件

5
我有一个包含多个记录的大型单个pdf文档。每个记录通常占用一页,但有些记录需要两页。每个记录都以定义的文本开头,这个文本总是相同的。
我的目标是将此pdf拆分为单独的pdf,并且在找到“标题文本”之前始终进行拆分。
注意:我正在寻找使用Java或Python的免费工具或库。必须在Win 7上可用。
有什么想法吗?据我所知,imagemagick无法完成此操作。itext可以吗?我从未使用过,而且它非常复杂,因此需要一些提示。
编辑:
标记答案引导我找到了解决方案。为了完整起见,这是我的确切实现:
public void splitByRegex(String filePath, String regex,
        String destinationDirectory, boolean removeBlankPages) throws IOException,
        DocumentException {

    logger.entry(filePath, regex, destinationDirectory);
    destinationDirectory = destinationDirectory == null ? "" : destinationDirectory;
    PdfReader reader = null;
    Document document = null;
    PdfCopy copy = null;
    Pattern pattern = Pattern.compile(regex);        

    try {
        reader = new PdfReader(filePath);
        final String RESULT = destinationDirectory + "/record%d.pdf";
        // loop over all the pages in the original PDF
        int n = reader.getNumberOfPages();
        for (int i = 1; i < n; i++) {

            final String text = PdfTextExtractor.getTextFromPage(reader, i);
            if (pattern.matcher(text).find()) {
                if (document != null && document.isOpen()) {
                    logger.debug("Match found. Closing previous Document..");
                    document.close();
                }
                String fileName = String.format(RESULT, i);
                logger.debug("Match found. Creating new Document " + fileName + "...");
                document = new Document();
                copy = new PdfCopy(document,
                        new FileOutputStream(fileName));
                document.open();
                logger.debug("Adding page to Document...");
                copy.addPage(copy.getImportedPage(reader, i));

            } else if (document != null && document.isOpen()) {
                logger.debug("Found Open Document. Adding additonal page to Document...");
                if (removeBlankPages && !isBlankPage(reader, i)){
                    copy.addPage(copy.getImportedPage(reader, i));
                }
            }
        }
        logger.exit();
    } finally {
        if (document != null && document.isOpen()) {
            document.close();
        }
        if (reader != null) {
            reader.close();
        }
    }
}

private boolean isBlankPage(PdfReader reader, int pageNumber)
        throws IOException {

    // see http://itext-general.2136553.n4.nabble.com/Detecting-blank-pages-td2144877.html
    PdfDictionary pageDict = reader.getPageN(pageNumber);
    // We need to examine the resource dictionary for /Font or
    // /XObject keys.  If either are present, they're almost
    // certainly actually used on the page -> not blank.
    PdfDictionary resDict = (PdfDictionary) pageDict.get(PdfName.RESOURCES);
    if (resDict != null) {
        return resDict.get(PdfName.FONT) == null
                && resDict.get(PdfName.XOBJECT) == null;
    } else {
        return true;
    }
}

如果PDF中的文本可以被正确解析,iText可以实现您想要的功能。您说,库必须是免费的。作为自由软件的iText需要您尊重AGPL许可证。 - mkl
这是关于编程的内容,需要将其翻译成中文。请仅返回翻译后的文本:这只是一次性的事情,所以AGPL不是问题。文本是可选择的(例如文本),因此应该可以工作。但是如果您知道任何代码示例,我很感兴趣。 - beginner_
目前我只能通过智能手机上网。稍后我会尝试找到一些示例代码。 - mkl
4个回答

5

您可以使用iText创建符合您要求的工具。

无论何时您需要关于(当前版本的)iText库的代码示例,都应该参考iText in Action — 2nd Edition,其代码示例可以在线搜索关键字here

在您的情况下,相关示例是Burst.javaExtractPageContentSorted2.java

Burst.java展示了如何将一个PDF文件分割成多个较小的PDF文件。其中心代码:

PdfReader reader = new PdfReader("allrecords.pdf");
final String RESULT = "record%d.pdf";

// We'll create as many new PDFs as there are pages
Document document;
PdfCopy copy;
// loop over all the pages in the original PDF
int n = reader.getNumberOfPages();
for (int i = 0; i < n; ) {
    // step 1
    document = new Document();
    // step 2
    copy = new PdfCopy(document,
            new FileOutputStream(String.format(RESULT, ++i)));
    // step 3
    document.open();
    // step 4
    copy.addPage(copy.getImportedPage(reader, i));
    // step 5
    document.close();
}
reader.close();

这个示例将PDF拆分为单页PDF。在您的情况下,您需要按不同的标准进行拆分。但这意味着在循环中有时需要添加多个导入的页面(因此要解耦循环索引和页面编号以进行导入)。
要识别新数据集开始的页面,请参考ExtractPageContentSorted2.java。该示例演示了如何将页面的文本内容解析为字符串。核心代码:
PdfReader reader = new PdfReader("allrecords.pdf");
for (int i = 1; i <= reader.getNumberOfPages(); i++) {
    System.out.println("\nPage " + i);
    System.out.println(PdfTextExtractor.getTextFromPage(reader, i));
}
reader.close();

只需搜索记录开始的文本:如果页面中包含该文本,则新的记录从那里开始。


谢谢,这非常方便。不过你的for循环需要一直执行到i <= n,否则你会漏掉源PDF的最后一页。 - Jeff Potts
这是不必要的。由于i在循环体内被递增,对于getImportedPage来说,这已经是一个从1到n的循环了。 - mkl

1
如果你喜欢 Python,有一个很好的库:PyPDF2。该库是纯python2编写,采用类似BSD的许可证。
示例代码:
from PyPDF2 import PdfFileWriter, PdfFileReader

input1 = PdfFileReader(open("C:\\Users\\Jarek\\Documents\\x.pdf", "rb"))

# analyze pdf data
print input1.getDocumentInfo()
print input1.getNumPages()
text = input1.getPage(0).extractText()
print text.encode("windows-1250", errors='backslashreplacee')

# create output document
output = PdfFileWriter()
output.addPage(input1.getPage(0))
fout = open("c:\\temp\\1\\y.pdf", "wb")
output.write(fout)
fout.close()

1

0

2
你的回答超出了上下文,那不是代码而是一个软件,这里不合适。 - Hugo Gresse

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接