我有231个pdf文件,并希望将每个文件转换为字符串格式。随后,我将每个字符串保存到txt文件中。
我能够为此创建一个代码(我检查它是否在我运行少量元素的代码时有效),但是即使10小时后python也没有完成程序的执行!
我使用" for loop"尝试了相同的代码,但它也太慢了。不知道怎样才能让这段代码变得更快?
这是我的代码:
from pdfminer.pdfinterp import PDFResourceManager,
PDFPageInterpreter#process_pdf
from pdfminer.pdfpage import PDFPage
from pdfminer.converter import TextConverter
from pdfminer.layout import LAParams
from io import StringIO
def pdf_to_text(pdfname):
# PDFMiner boilerplate
rsrcmgr = PDFResourceManager()
sio = StringIO()
codec = 'utf-8'
laparams = LAParams()
device = TextConverter(rsrcmgr, sio, codec=codec, laparams=laparams)
interpreter = PDFPageInterpreter(rsrcmgr, device)
# Extract text
fp = open(pdfname, 'rb')
for page in PDFPage.get_pages(fp):
interpreter.process_page(page)
fp.close()
# Get text from StringIO
text = sio.getvalue()
# Cleanup
device.close()
sio.close()
return text
lista2 = [pdf_to_text(k) for k in lista1]
其中lista1是我的231 pdfs的列表
pdf文件是从website中提取的。我只选择了带有" Livro"这个词的文件。在名称中。
答案 0 :(得分:1)
这是生成器的一个很好的用例:节省内存。
通常,您需要做的就是迭代文件,一次转换一个文件,然后将输出流式传输到其他地方。比方说,例如:
for f in files:
text = pdf_to_text(f)
output.write(text)
- 那么你不想要(或需要)列表理解,实际上你根本不需要创建列表。相反,请考虑一次迭代一个元素。或者创建一个生成器,如果这更有意义。
请记住,如果您仍然有对它的引用,则垃圾收集器无法释放内存。如果创建列表推导,那么它中的所有元素(以及这些元素引用的项)必须一次性保存在内存中。通常,如果您计划频繁或以非线性顺序访问元素,则只需要这样做。
您还应该考虑,即使您可以执行allocate
/ transform
/ deallocate
,处理大型文件的可能性仍然太慢"如果我们正在谈论值得阅读/写入的许多千兆字节。在这种情况下,最好的选择通常是考虑使用C扩展,以便更好地控制内存的分配和使用方式。此外,pypy
适用于绝大多数情况,通常比CPython快得多。
答案 1 :(得分:0)
您正在处理的文件看起来很大(10MB),因此预计会有很长的执行时间。除了更多的并行化和对内存更加谨慎之外,你无法做很多事情来加速程序的执行。也就是说,您可以执行以下操作:
multiprocessing.Pool
这是一个包含这些优化的完整程序:
#!/usr/bin/env python
import os
from multiprocessing import Pool, cpu_count
from io import BytesIO
from pdfminer.pdfinterp import PDFResourceManager, PDFPageInterpreter
from pdfminer.pdfpage import PDFPage
from pdfminer.converter import TextConverter
from pdfminer.layout import LAParams
PDF_DIRECTORY = "pdfs"
def pdf_to_text(pdf_filename):
# PDFMiner boilerplate
pdf_resource_manager = PDFResourceManager()
bytes_io = BytesIO()
device = TextConverter(
pdf_resource_manager, bytes_io, codec="utf-8", laparams=LAParams())
interpreter = PDFPageInterpreter(pdf_resource_manager, device)
# Extract text
with open(pdf_filename, "rb") as fp:
for page in PDFPage.get_pages(fp):
interpreter.process_page(page)
text = str(bytes_io.getvalue())
# Cleanup
bytes_io.close()
device.close()
# Print current filename with some of the parsed text
print("{} - {}".format(pdf_filename, text[:15].replace("\n", "")))
return text
def process_pdf_file(pdf_filename):
text_filename = "{}.txt".format(os.path.splitext(pdf_filename)[0])
# Write the text file to disk to avoid having to keep
# it in memory
with open(text_filename, "w") as text_file:
text_file.write(pdf_to_text(pdf_filename))
def main():
pdf_filename_list = []
for filename in os.listdir(PDF_DIRECTORY):
if not filename.endswith(".pdf"):
continue
pdf_filename_list.append(os.path.join(PDF_DIRECTORY, filename))
MULTITHREAD = True
if MULTITHREAD:
# Use a thread pool to process multiple PDF files at the same time
pool = Pool(cpu_count())
pool.map(process_pdf_file, pdf_filename_list)
else:
# Version without thread pool
for pdf_filename in pdf_filename_list:
process_pdf_file(pdf_filename)
main()