2009-12-16 10 views
5

पर आधारित एक पीडीएफ विभाजित करें, मैं रूपरेखा के आधार पर पीडीएफ फ़ाइल को विभाजित करने के लिए पीपीपीडीएफ का उपयोग करना चाहता हूं, जहां रूपरेखा में प्रत्येक गंतव्य पीडीएफ के भीतर एक अलग पृष्ठ को संदर्भित करता है।रूपरेखा

उदाहरण रूपरेखा:

 
main  --> points to page 1 
    sect1 --> points to page 1 
    sect2 --> points to page 15 
    sect3 --> points to page 22 

यह दस्तावेज़ या दस्तावेज़ की रूपरेखा में प्रत्येक गंतव्य के प्रत्येक पृष्ठ के ऊपर दोहराने में pyPdf भीतर आसान है; हालांकि, मैं यह नहीं समझ सकता कि गंतव्य बिंदुओं को पृष्ठ संख्या कैसे प्राप्त करें।

क्या कोई जानता है कि रूपरेखा में प्रत्येक गंतव्य के लिए संदर्भ पृष्ठ संख्या कैसे प्राप्त करें?

उत्तर

6

मैं इसे लगा आउट:

 
    class Darrell(pyPdf.PdfFileReader): 

     def getDestinationPageNumbers(self): 
      def _setup_outline_page_ids(outline, _result=None): 
       if _result is None: 
        _result = {} 
       for obj in outline: 
        if isinstance(obj, pyPdf.pdf.Destination): 
         _result[(id(obj), obj.title)] = obj.page.idnum 
        elif isinstance(obj, list): 
         _setup_outline_page_ids(obj, _result) 
       return _result 

      def _setup_page_id_to_num(pages=None, _result=None, _num_pages=None): 
       if _result is None: 
        _result = {} 
       if pages is None: 
        _num_pages = [] 
        pages = self.trailer["/Root"].getObject()["/Pages"].getObject() 
       t = pages["/Type"] 
       if t == "/Pages": 
        for page in pages["/Kids"]: 
         _result[page.idnum] = len(_num_pages) 
         _setup_page_id_to_num(page.getObject(), _result, _num_pages) 
       elif t == "/Page": 
        _num_pages.append(1) 
       return _result 

      outline_page_ids = _setup_outline_page_ids(self.getOutlines()) 
      page_id_to_page_numbers = _setup_page_id_to_num() 

      result = {} 
      for (_, title), page_idnum in outline_page_ids.iteritems(): 
       result[title] = page_id_to_page_numbers.get(page_idnum, '???') 
      return result 

    pdf = Darrell(open(PATH-TO-PDF, 'rb')) 
    template = '%-5s %s' 
    print template % ('page', 'title') 
    for p,t in sorted([(v,k) for k,v in pdf.getDestinationPageNumbers().iteritems()]): 
     print template % (p+1,t) 
1

डेरेल की क्लास थोड़ा संशोधित किया जा सकता है एक PDF के लिए सामग्री की एक बहु स्तरीय तालिका का निर्माण करने के

(pdftk टूलकिट में pdftoc के तरीके से।) मेरा संशोधन _setup_page_id_to_num, एक पूर्णांक "स्तर" पर एक और पैरामीटर जोड़ता है जो 1 को डिफ़ॉल्ट करता है। प्रत्येक आमंत्रण स्तर को बढ़ाता है। नतीजतन केवल पृष्ठ संख्या को संग्रहीत करने के बजाय, हम पृष्ठ संख्या और स्तर की जोड़ी संग्रहीत करते हैं। लौटा परिणाम का उपयोग करते समय उचित संशोधन लागू किया जाना चाहिए।

मैं इसका उपयोग "पीडीएफ हैक्स" ब्राउज़र-आधारित पेज-एट-टाइम दस्तावेज़ व्यूअर को सामग्री की एक साइडबार तालिका के साथ लागू करने के लिए कर रहा हूं जो लाटेक्स अनुभाग, उपखंड आदि बुकमार्क को दर्शाता है। मैं एक साझा सिस्टम पर काम कर रहा हूं जहां पीडीएफटीके स्थापित नहीं किया जा सकता है, लेकिन जहां पाइथन उपलब्ध है।

0

यह वही है जो मैं ढूंढ रहा था। PdfFileReader के लिए Darrell के परिवर्धन पीईपीडीएफ 2 का हिस्सा होना चाहिए।

मैंने एक छोटी सी नुस्खा लिखी जो पीडीएफडीएफ 2 और सीजेडीए-कंसोल का उपयोग बुकमार्क्स द्वारा पीडीएफ को विभाजित करने के लिए करता है। मेरे मामले में कई स्तर 1 खंड हैं जिन्हें मैं एक साथ रखना चाहता हूं। यह स्क्रिप्ट मुझे ऐसा करने की अनुमति देती है और परिणामी फाइलों को सार्थक नाम देती है। @darrell वर्ग के लिए

import operator 
import os 
import subprocess 
import sys 
import time 

import PyPDF2 as pyPdf 

# need to have sejda-console installed 
# change this to point to your installation 
sejda = 'C:\\sejda-console-1.0.0.M2\\bin\\sejda-console.bat' 

class Darrell(pyPdf.PdfFileReader): 
    ... 

if __name__ == '__main__': 
    t0= time.time() 

    # get the name of the file to split as a command line arg 
    pdfname = sys.argv[1] 

    # open up the pdf 
    pdf = Darrell(open(pdfname, 'rb')) 

    # build list of (pagenumbers, newFileNames) 
    splitlist = [(1,'FrontMatter')] # Customize name of first section 

    template = '%-5s %s' 
    print template % ('Page', 'Title') 
    print '-'*72 
    for t,p in sorted(pdf.getDestinationPageNumbers().iteritems(), 
         key=operator.itemgetter(1)): 

     # Customize this to get it to split where you want 
     if t.startswith('Chapter') or \ 
      t.startswith('Preface') or \ 
      t.startswith('References'): 

      print template % (p+1, t) 

      # this customizes how files are renamed 
      new = t.replace('Chapter ', 'Chapter')\ 
        .replace(': ', '-')\ 
        .replace(': ', '-')\ 
        .replace(' ', '_') 
      splitlist.append((p+1, new)) 

    # call sejda tools and split document 
    call = sejda 
    call += ' splitbypages' 
    call += ' -f "%s"'%pdfname 
    call += ' -o ./' 
    call += ' -n ' 
    call += ' '.join([str(p) for p,t in splitlist[1:]]) 
    print '\n', call 
    subprocess.call(call) 
    print '\nsejda-console has completed.\n\n' 

    # rename the split files 
    for p,t in splitlist: 
     old ='./%i_'%p + pdfname 
     new = './' + t + '.pdf' 
     print 'renaming "%s"\n  to "%s"...'%(old, new), 

     try: 
      os.remove(new) 
     except OSError: 
      pass 

     try: 
      os.rename(old, new) 
      print' succeeded.\n' 
     except: 
      print' failed.\n' 

    print '\ndone. Spliting took %.2f seconds'%(time.time() - t0) 
0

छोटे अद्यतन क्योंकि टिप्पणी पढ़ने के लिए मुश्किल होगा UTF-8 रूपरेखा है, जो मैं जवाब के रूप में पोस्ट पार्स करने के लिए सक्षम होने के लिए।

समस्या pyPdf.pdf.Destination.title में है जो दो रूपों में लौटाया जा सकता है:

  • pyPdf.generic.TextStringObject
  • pyPdf.generic.ByteStringObject

तो _setup_outline_page_ids() समारोह से कि उत्पादन भी दो अलग अलग प्रकार title वस्तु है, जो विफल रहता है के लिए रिटर्न UnicodeDecodeError के साथ यदि रूपरेखा शीर्षक में कुछ भी है तो ASCII।

if isinstance(title, pyPdf.generic.TextStringObject): 
    title = title.encode('utf-8') 
पूरी कक्षा की

:

class PdfOutline(pyPdf.PdfFileReader): 

    def getDestinationPageNumbers(self): 

     def _setup_outline_page_ids(outline, _result=None): 
      if _result is None: 
       _result = {} 
      for obj in outline: 
       if isinstance(obj, pyPdf.pdf.Destination): 
        _result[(id(obj), obj.title)] = obj.page.idnum 
       elif isinstance(obj, list): 
        _setup_outline_page_ids(obj, _result) 
      return _result 

     def _setup_page_id_to_num(pages=None, _result=None, _num_pages=None): 
      if _result is None: 
       _result = {} 
      if pages is None: 
       _num_pages = [] 
       pages = self.trailer["/Root"].getObject()["/Pages"].getObject() 
      t = pages["/Type"] 
      if t == "/Pages": 
       for page in pages["/Kids"]: 
        _result[page.idnum] = len(_num_pages) 
        _setup_page_id_to_num(page.getObject(), _result, _num_pages) 
      elif t == "/Page": 
       _num_pages.append(1) 
      return _result 

     outline_page_ids = _setup_outline_page_ids(self.getOutlines()) 
     page_id_to_page_numbers = _setup_page_id_to_num() 

     result = {} 
     for (_, title), page_idnum in outline_page_ids.iteritems(): 
      if isinstance(title, pyPdf.generic.TextStringObject): 
       title = title.encode('utf-8') 
      result[title] = page_id_to_page_numbers.get(page_idnum, '???') 
     return result 

मैं समस्या को हल करने के लिए इस कोड जोड़ा

संबंधित मुद्दे