您可以像這樣從 PDF 中提取文本:

from PyPDF2 import PdfReader

reader = PdfReader("example.pdf")
page = reader.pages[0]
print(page.extract_text())

您還可以選擇限制要提取的文本方向,例如:

# extract only text oriented up
print(page.extract_text(0))

# extract text oriented up and turned left
print(page.extract_text((0, 90)))

Using a visitor(使用訪客)

您可以使用訪問者功能來控制要處理和提取頁面的哪一部分。您提供的訪問者函數(shù)將為每個運算符或每個文本片段調(diào)用。

在函數(shù) extract_text 的參數(shù) visitor_text 中提供的函數(shù)有五個參數(shù):當前轉(zhuǎn)換矩陣、文本矩陣、字體字典和字體大小。在大多數(shù)情況下,當前位置的 x 和 y 坐標位于當前變換矩陣的索引 4 和 5 中。

在未知字體的情況下,字體字典可能是無。如果不是 None 它可能例如包含鍵“/BaseFont”和值“/Arial,Bold”。

警告:在復(fù)雜的文檔中,計算出的位置可能是錯誤的。

參數(shù) visitor_operand_before 中提供的函數(shù)有四個參數(shù):操作數(shù)、操作數(shù)參數(shù)、當前轉(zhuǎn)換矩陣和文本矩陣。

示例 2:將矩形和文本提取到 SVG 文件中

以下示例將此 PDF 文檔的第 3 頁轉(zhuǎn)換為 SVG 文件。

這樣的 SVG 導(dǎo)出可能有助于理解頁面中發(fā)生的事情。

from PyPDF2 import PdfReader
import svgwrite

reader = PdfReader("GeoBase_NHNC1_Data_Model_UML_EN.pdf")
page = reader.pages[2]

dwg = svgwrite.Drawing("GeoBase_test.svg", profile="tiny")


def visitor_svg_rect(op, args, cm, tm):
    if op == b"re":
        (x, y, w, h) = (args[i].as_numeric() for i in range(4))
        dwg.add(dwg.rect((x, y), (w, h), stroke="red", fill_opacity=0.05))


def visitor_svg_text(text, cm, tm, fontDict, fontSize):
    (x, y) = (tm[4], tm[5])
    dwg.add(dwg.text(text, insert=(x, y), fill="blue"))


page.extract_text(
    visitor_operand_before=visitor_svg_rect, visitor_text=visitor_svg_text
)
dwg.save()

這里生成的SVG是自下而上的,因為PDF和SVG的坐標系不同。

不幸的是,在復(fù)雜的 PDF 文檔中,提供給訪問者功能的坐標可能是錯誤的。

為什么文本提取很難

從 PDF 中提取文本可能非常棘手。在某些情況下,沒有明確的答案預(yù)期結(jié)果應(yīng)該是什么樣子:

  1. Paragraphs: 一個段落的文本是否應(yīng)該在原始 PDF 的相同位置有換行符,或者它應(yīng)該是一個文本塊?

  2. Page numbers: 它們應(yīng)該包含在摘錄中嗎?

  3. Headers and Footers: 類似于頁碼 - 是否應(yīng)該提取它們?

  4. Outlines: 是否應(yīng)該提取輪廓?

  5. Formatting: 如果文本是粗體或斜體,它應(yīng)該包含在輸出中嗎?

  6. Tables: 文本提取是否應(yīng)該跳過表格?它應(yīng)該只提取文本嗎?邊框是否應(yīng)該以某種類似 Markdown 的方式顯示,或者結(jié)構(gòu)是否應(yīng)該存在,例如作為 HTML 表格?你將如何處理合并的單元格?

  7. Captions: 是否應(yīng)包括圖像和表格標題?

  8. Ligatures: Unicode 符號 U+FB00 是兩個小寫字母“f”的單個符號 ff。應(yīng)該將其解析為 Unicode 符號“ff”還是兩個 ASCII 符號“ff”?

  9. SVG images: 是否應(yīng)該提取文本部分?

  10. Mathematical Formulas: 他們應(yīng)該被提取嗎?公式有索引和嵌套分數(shù)。

  11. Whitespace characters: 對于 3cm 的垂直空白應(yīng)該提取多少行?如果有 3cm 的水平空白,應(yīng)該提取多少個空格?你什么時候提取制表符,什么時候提取空格?

  12. Footnotes: 提取多頁正文時,腳注應(yīng)該放在哪里?

  13. Hyperlinks and Metadata: 它應(yīng)該被提取嗎?它應(yīng)該以哪種格式放置在哪里?

  14. Linearization: 假設(shè)您在段落之間有一個浮動圖形。你是先完成段落還是在中間放置圖形文本?

還有一些問題,大多數(shù)人會同意正確的輸出,但 PDF 存儲信息的方式很難實現(xiàn):

  1. Tables: 通常,表格只是絕對定位的文本。在最壞的情況下,任何一個字母都可以被絕對定位。這使得很難分辨列/行在哪里。

  2. Images: 有時 PDF 不包含顯示的文本,而是圖像。當您無法復(fù)制文本時,您會注意到這一點。然后是在背景中包含圖像和文本層的 PDF 文件。這通常發(fā)生在掃描文檔時。雖然今天的掃描軟件(OCR)已經(jīng)很不錯了,但偶爾還是會出現(xiàn)故障。 PyPDF2 不是 OCR 軟件;它將無法檢測到這些故障。 PyPDF2 也永遠無法從圖像中提取文本。

最后還有 PyPDF2 將處理的問題。如果您發(fā)現(xiàn)此類文本提取錯誤,請與我們分享 PDF,以便我們進行處理!

OCR 與文本提取

光學(xué)字符識別 (OCR) 是從圖像中提取文本的過程。執(zhí)行此操作的軟件稱為 OCR 軟件。 tesseract OCR 引擎是最廣為人知的開源 OCR 軟件。

PyPDF2 不是 OCR 軟件。

數(shù)字生成與掃描的 PDF 文件

PDF 文檔可以包含圖像和文本。 PDF 文件不以語義上有意義的方式存儲文本,而是以一種便于在屏幕上顯示或打印文本的方式。由于這個原因,從 PDF 中提取文本很困難。

如果您掃描文檔,生成的 PDF 通常會顯示掃描圖像。然后掃描儀還運行 OCR 軟件并將識別出的文本放在圖像的背景中。掃描儀 OCR 軟件的結(jié)果可以通過 PyPDF2 提取。但是,在這種情況下,建議直接使用 OCR 軟件,因為錯誤會累積:OCR 軟件在識別文本方面并不完美。然后它以一種不適用于文本提取的格式存儲文本,PyPDF2 可能會在解析該格式時出錯。

因此,我會區(qū)分三種類型的 PDF 文檔:

  • Digitally-born PDF files: 該文件是在計算機上以數(shù)字方式創(chuàng)建的。它可以包含圖像、文本、鏈接、大綱項目(又名書簽)、JavaScript ……如果放大很多,文本看起來仍然清晰。

  • Scanned PDF files: 掃描了任意數(shù)量的頁面。然后將圖像存儲在 PDF 文件中。因此,該文件只是這些圖像的容器。你不能復(fù)制文本,你沒有鏈接、大綱項目、JavaScript。

  • OCRed PDF files: 掃描儀運行 OCR 軟件并將識別出的文本放在圖像的背景中。因此您可以復(fù)制文本,但它看起來仍然像掃描件。如果放大足夠大,您可以識別像素。

我們可以一直使用 OCR 嗎?

您現(xiàn)在可能想知道始終使用 OCR 軟件是否有意義。如果 PDF 文件是數(shù)字生成的,您可以將其渲染為圖像。

我建議不要那樣做。

PyPDF2 等文本提取軟件可以使用 PDF 中的更多信息,而不僅僅是圖像。它可以了解字體、編碼、典型字符距離和類似主題。

這意味著 PyPDF2 在處理容易混淆的字符(例如 ?oO0??)時具有明顯的優(yōu)勢。 PyPDF2 永遠不會混淆字符。它只是讀取文件中的內(nèi)容。

PyPDF2 在處理稀有字符時也有優(yōu)勢,例如. OCR 軟件將無法正確識別笑臉符號。

試圖阻止文本提取

如果共享 PDF 文檔的人想要阻止文本提取,有多種方法可以做到:

  1. 將 PDF 的內(nèi)容存儲為圖像

  2. 使用亂碼字體

但是,如果人們?nèi)詰?yīng)能夠閱讀文檔,則不能完全阻止文本提取。在最壞的情況下,人們可以截屏、打印、掃描并在其上運行 OCR。