首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >将多个pdf文件中的特定页面写入一个新pdf文件

将多个pdf文件中的特定页面写入一个新pdf文件
EN

Stack Overflow用户
提问于 2022-02-07 09:06:10
回答 1查看 215关注 0票数 0

我有多个pdf文件,我想提取一组特定的页面,其中每组页面是不同的每一个pdf文件。我已经创建了一个字典,其中键作为pdf文件名,值作为从每个pdf文件中提取的页面列表(显示为键)。我打算从相关的pdf文件中提取给定的页面,并将它们全部写入一个新的pdf文件中,以便我可以在这个最终文件上进行数据提取。我尝试过PyPDF4和FPDF,但到目前为止还没有joy给我一个很大的pdf和空白页,或者一个pdf只提取了1到2页,或者找不到pdf对象的错误。我希望能得到一些关于我的方法哪里出错的指导。下面是我的代码:

代码语言:javascript
复制
import PyPDF4
from PyPDF4 import PdfFileReader, PdfFileWriter

for pdf,pgs in dic_11_1.items():
  pdf=list(dic_11_1.keys())
  pgs=list(dic_11_1.values())
  for i in range(0,len(pdf)):
    pages = pgs[i]
    object = open(pdf[i],'rb') 
    pdfinput=PyPDF4.PdfFileReader(object,'rb')
    if pdfinput.isEncrypted:
        pdfinput.decrypt('')
    else:
        pdfinput
    for p in pages:
        page=pdfinput.getPage(p)
        pdf_writer=PyPDF4.PdfFileWriter()
        pdf_writer.addPage(page)
        with open('F111.pdf',mode='wb') as output:
            pdf_writer.write(output)

我得到的错误是'PdfReadError:找不到对象。‘

当我使用下面的代码尝试FPDF时,它会运行很长时间,并给出一个大的空pdf文件:

代码语言:javascript
复制
from fpdf import FPDF 
import os
for pdf,pgs in dic_11_1.items():
  pdf_in=open(pdf,'rb')
  inputpdf=PdfFileReader(pdf_in,'rb')
  if inputpdf.isEncrypted:
    inputpdf.decrypt('')
  else:
    inputpdf
  for p in pgs:
    content=inputpdf.getPage(p).extractText()
    pdf = FPDF('P','mm','A4') 
    pdf.add_page() 
    pdf.set_font("arial", size = 10) 
    for text in content: 
        text2=text.encode('latin-1', 'replace').decode('latin-1')
        pdf.write(10,text2) 
        pdf.ln(8)
        pdf.close()
        return_byte_string=pdf.output('F_11_1.pdf','S').encode('latin-1')
    pdf_file=open('F_11_1.pdf','wb')
    pdf_file.write(return_byte_string)
    pdf_file.close()

如有任何指导,将不胜感激。提前谢谢你

@SUTerliakov提供的解决方案很棒,但只从页面的字典值列表中编写了最后一页或最后一份文档。它是通过代码中的一个小缩进来解析的,这为我获得了所有的数据。再次感谢SUTerliakov让我走上正确的道路!这是您调整后的代码:

代码语言:javascript
复制
pdf_writer = PdfFileWriter()
open_files = []

try:
   for filename, pgs in dic_11_1.items():
      src = open(filename, 'rb')
      open_files.append(src)
 
      pdfinput = PdfFileReader(src, 'rb')

      if pdfinput.isEncrypted:
        pdfinput.decrypt('')
        print(f'Extracting relevant pages from {filename} to central repository') 
        for p in pgs:
           print(f'{filename} pg{str(p)}')
           pdf_writer.addPage(pdfinput.getPage(p))
        print(f'Writing {len(pgs)} pages to central file')
   Stream=open('F_11_1.pdf','wb')    
   pdf_writer.write(Stream)
finally:
   print('Closing Source File...')
   for f in open_files:
      f.close()
EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2022-02-07 09:24:11

问题是你没有正确地迭代。请参阅代码中的注释,以更好地理解。

UPD。PyPDF4似乎只添加了对PdfFileWriter的页面引用,直到它实际写入某个文件为止。因此,我们可以关闭输入源,只有在最后。因此,此方法不适用于大型文件计数(在linux上,它将受到ulimit的限制,默认为1024,因此我们只能打开1000个输入文件+1个输出文件+3个系统流-- stdin、stdout、stderr;这个限制可以用ulimit -n <count>扩大)。

代码语言:javascript
复制
from PyPDF4 import PdfFileReader, PdfFileWriter


sect_11_1 = [
    ('filename1.pdf', 0, 1),
    ('filename2.pdf', 0, 1),
]
# note pages are zero-numbered

dic_11_1 = {}

# if sect_11_1 is of another format 
# [('filename', [0, 1]), ...]
# remove star below
for filename, *pages in sect_11_1:
    dic_11_1.setdefault(filename, [])
    dic_11_1[filename].extend(pages)

# if filenames are not repeated, you can do just
# dic_11_1 = dict(sect_11_1)

# you need single writer for all files, don't declare it in a loop
pdf_writer = PdfFileWriter()
open_files = []

try:
    for filename, pages in dic_11_1.items():
        # now you have filename and pages set to 'filename1.pdf' and [1, 3, 4]
        # on second iteration they'll be set to 'filename2.pdf' and [0, 2, 3]
        # ...

        # don't use `object` as variable name: it's valid, but bad style
        # (it shadows builtin `object`)
        
        src = open(filename, 'rb')
        open_files.append(src)
     
        pdfinput = PdfFileReader(src, 'rb')

        if pdfinput.isEncrypted:
            pdfinput.decrypt('')
            # you don't need empty `else`

        for p in pages:
            # you might want to use `p - 1` instead if your input was 1-numbered
            page = pdfinput.getPage(p)
            pdf_writer.addPage(page)

    # when all pages are added, write to output
    with open('F111.pdf',mode='wb') as output:
        pdf_writer.write(output)
finally:  # if something was wrong, do it anyway
    for f in open_files:
        f.close()  # we shouldn't keep files open after program run
票数 -1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/71015913

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档