如何使用 OCR 有效地从 PDF 文件目录中提取文本?
How to extract text from a directory of PDF files efficiently with OCR?
我有一个包含 PDF 文件 (images) 的大目录,我怎样才能有效地从目录中的所有文件中提取文本?。到目前为止,我尝试过:
import multiprocessing
import textract
def extract_txt(file_path):
text = textract.process(file_path, method='tesseract')
p = multiprocessing.Pool(2)
file_path = ['/Users/user/Desktop/sample.pdf']
list(p.map(extract_txt, file_path))
但是,它不起作用...需要很多时间(我有一些文档有 600 页)。另外:a)我不知道如何有效地处理目录转换部分。 b) 我想添加一个页面分隔符,比方说:<start/age = 1> ... page content ... <end/page = 1>
,但我不知道该怎么做。
因此,我如何将 extract_txt
函数应用到一个目录中以 .pdf
和 return 结尾的所有元素相同的文件在另一个目录中,但在 .txt
格式,并添加带有 OCR 文本提取的页面分隔符?。
此外,我很好奇使用 google 文档来完成这项任务,是否可以通过编程方式使用 google 文档来解决上述文本提取问题?
更新
关于 "adding a page separator" 问题 (<start/age = 1> ... page content ... <end/page = 1>
) 在阅读 Roland Smith 的回答后我尝试:
from PyPDF2 import PdfFileWriter, PdfFileReader
import textract
def extract_text(pdf_file):
inputpdf = PdfFileReader(open(pdf_file, "rb"))
for i in range(inputpdf.numPages):
w = PdfFileWriter()
w.addPage(inputpdf.getPage(i))
outfname = 'page{:03d}.pdf'.format(i)
with open(outfname, 'wb') as outfile: # I presume you need `wb`.
w.write(outfile)
print('\n<begin page pos =' , i, '>\n')
text = textract.process(str(outfname), method='tesseract')
os.remove(outfname) # clean up.
print(str(text, 'utf8'))
print('\n<end page pos =' , i, '>\n')
extract_text('/Users/user/Downloads/ImageOnly.pdf')
但是,print()
部分仍然存在问题,因为与其打印,不如将所有输出保存到文件中更有用。因此,我试图将输出重定向到一个文件:
sys.stdout=open("test.txt","w")
print('\n<begin page pos =' , i, '>\n')
sys.stdout.close()
text = textract.process(str(outfname), method='tesseract')
os.remove(outfname) # clean up.
sys.stdout=open("test.txt","w")
print(str(text, 'utf8'))
sys.stdout.close()
sys.stdout=open("test.txt","w")
print('\n<end page pos =' , i, '>\n')
sys.stdout.close()
知道如何制作页面 extraction/separator 技巧并将所有内容保存到文件中吗?...
在您的代码中,您正在提取文本,但您没有对其进行任何操作。
尝试这样的事情:
def extract_txt(file_path):
text = textract.process(file_path, method='tesseract')
outfn = file_path[:-4] + '.txt' # assuming filenames end with '.pdf'
with open(outfn, 'wb') as output_file:
output_file.write(text)
return file_path
这会将文本写入具有相同名称但扩展名为 .txt
的文件。
它还returns原始文件的路径,让家长知道这个文件已经完成。
所以我会将映射代码更改为:
p = multiprocessing.Pool()
file_path = ['/Users/user/Desktop/sample.pdf']
for fn in p.imap_unordered(extract_txt, file_path):
print('completed file:', fn)
- 创建
Pool
时不需要给出参数。默认情况下,它将创建与 cpu-cores 一样多的 worker。
- 使用
imap_unordered
创建一个迭代器,一旦值可用就开始产生值。
- 因为worker函数返回了文件名,你可以打印它让用户知道这个文件已经完成了。
编辑 1:
另一个问题是是否可以标记页面边界。我觉得是。
一种肯定可行的方法是在OCR 之前将PDF 文件分成页。你可以使用例如pdfinfo
从 poppler-utils 包中找出文档中的页数。然后你可以使用例如pdfseparate
来自同一个 poppler-utils 包,将 N 页的一个 pdf 文件转换为一页的 N 个 pdf 文件。然后您可以单独对单页 PDF 文件进行 OCR。这将分别为您提供每一页上的文本。
或者,您可以对整个文档进行 OCR,然后搜索分页符。这 仅在文档的每一页上都有固定的或可预测的页眉或页脚时才有效 。它可能不如上述方法可靠。
编辑 2:
如果需要文件,写一个文件:
from PyPDF2 import PdfFileWriter, PdfFileReader
import textract
def extract_text(pdf_file):
inputpdf = PdfFileReader(open(pdf_file, "rb"))
outfname = pdf_file[:-4] + '.txt' # Assuming PDF file name ends with ".pdf"
with open(outfname, 'w') as textfile:
for i in range(inputpdf.numPages):
w = PdfFileWriter()
w.addPage(inputpdf.getPage(i))
outfname = 'page{:03d}.pdf'.format(i)
with open(outfname, 'wb') as outfile: # I presume you need `wb`.
w.write(outfile)
print('page', i)
text = textract.process(outfname, method='tesseract')
# Add header and footer.
text = '\n<begin page pos = {}>\n'.format(i) + text + '\n<end page pos = {}>\n'.format(i)
# Write the OCR-ed text to the output file.
textfile.write(text)
os.remove(outfname) # clean up.
print(text)
我有一个包含 PDF 文件 (images) 的大目录,我怎样才能有效地从目录中的所有文件中提取文本?。到目前为止,我尝试过:
import multiprocessing
import textract
def extract_txt(file_path):
text = textract.process(file_path, method='tesseract')
p = multiprocessing.Pool(2)
file_path = ['/Users/user/Desktop/sample.pdf']
list(p.map(extract_txt, file_path))
但是,它不起作用...需要很多时间(我有一些文档有 600 页)。另外:a)我不知道如何有效地处理目录转换部分。 b) 我想添加一个页面分隔符,比方说:<start/age = 1> ... page content ... <end/page = 1>
,但我不知道该怎么做。
因此,我如何将 extract_txt
函数应用到一个目录中以 .pdf
和 return 结尾的所有元素相同的文件在另一个目录中,但在 .txt
格式,并添加带有 OCR 文本提取的页面分隔符?。
此外,我很好奇使用 google 文档来完成这项任务,是否可以通过编程方式使用 google 文档来解决上述文本提取问题?
更新
关于 "adding a page separator" 问题 (<start/age = 1> ... page content ... <end/page = 1>
) 在阅读 Roland Smith 的回答后我尝试:
from PyPDF2 import PdfFileWriter, PdfFileReader
import textract
def extract_text(pdf_file):
inputpdf = PdfFileReader(open(pdf_file, "rb"))
for i in range(inputpdf.numPages):
w = PdfFileWriter()
w.addPage(inputpdf.getPage(i))
outfname = 'page{:03d}.pdf'.format(i)
with open(outfname, 'wb') as outfile: # I presume you need `wb`.
w.write(outfile)
print('\n<begin page pos =' , i, '>\n')
text = textract.process(str(outfname), method='tesseract')
os.remove(outfname) # clean up.
print(str(text, 'utf8'))
print('\n<end page pos =' , i, '>\n')
extract_text('/Users/user/Downloads/ImageOnly.pdf')
但是,print()
部分仍然存在问题,因为与其打印,不如将所有输出保存到文件中更有用。因此,我试图将输出重定向到一个文件:
sys.stdout=open("test.txt","w")
print('\n<begin page pos =' , i, '>\n')
sys.stdout.close()
text = textract.process(str(outfname), method='tesseract')
os.remove(outfname) # clean up.
sys.stdout=open("test.txt","w")
print(str(text, 'utf8'))
sys.stdout.close()
sys.stdout=open("test.txt","w")
print('\n<end page pos =' , i, '>\n')
sys.stdout.close()
知道如何制作页面 extraction/separator 技巧并将所有内容保存到文件中吗?...
在您的代码中,您正在提取文本,但您没有对其进行任何操作。
尝试这样的事情:
def extract_txt(file_path):
text = textract.process(file_path, method='tesseract')
outfn = file_path[:-4] + '.txt' # assuming filenames end with '.pdf'
with open(outfn, 'wb') as output_file:
output_file.write(text)
return file_path
这会将文本写入具有相同名称但扩展名为 .txt
的文件。
它还returns原始文件的路径,让家长知道这个文件已经完成。
所以我会将映射代码更改为:
p = multiprocessing.Pool()
file_path = ['/Users/user/Desktop/sample.pdf']
for fn in p.imap_unordered(extract_txt, file_path):
print('completed file:', fn)
- 创建
Pool
时不需要给出参数。默认情况下,它将创建与 cpu-cores 一样多的 worker。 - 使用
imap_unordered
创建一个迭代器,一旦值可用就开始产生值。 - 因为worker函数返回了文件名,你可以打印它让用户知道这个文件已经完成了。
编辑 1:
另一个问题是是否可以标记页面边界。我觉得是。
一种肯定可行的方法是在OCR 之前将PDF 文件分成页。你可以使用例如pdfinfo
从 poppler-utils 包中找出文档中的页数。然后你可以使用例如pdfseparate
来自同一个 poppler-utils 包,将 N 页的一个 pdf 文件转换为一页的 N 个 pdf 文件。然后您可以单独对单页 PDF 文件进行 OCR。这将分别为您提供每一页上的文本。
或者,您可以对整个文档进行 OCR,然后搜索分页符。这 仅在文档的每一页上都有固定的或可预测的页眉或页脚时才有效 。它可能不如上述方法可靠。
编辑 2:
如果需要文件,写一个文件:
from PyPDF2 import PdfFileWriter, PdfFileReader
import textract
def extract_text(pdf_file):
inputpdf = PdfFileReader(open(pdf_file, "rb"))
outfname = pdf_file[:-4] + '.txt' # Assuming PDF file name ends with ".pdf"
with open(outfname, 'w') as textfile:
for i in range(inputpdf.numPages):
w = PdfFileWriter()
w.addPage(inputpdf.getPage(i))
outfname = 'page{:03d}.pdf'.format(i)
with open(outfname, 'wb') as outfile: # I presume you need `wb`.
w.write(outfile)
print('page', i)
text = textract.process(outfname, method='tesseract')
# Add header and footer.
text = '\n<begin page pos = {}>\n'.format(i) + text + '\n<end page pos = {}>\n'.format(i)
# Write the OCR-ed text to the output file.
textfile.write(text)
os.remove(outfname) # clean up.
print(text)