pyPDF

2012-09-10 5 views
8

पल मैं pyPdf के साथ विलय कुछ PDF करने में देख रहा हूँ पर साथ दस्तावेज़ से पृष्ठ संख्या को पुनः प्राप्त, लेकिन कभी कभी आदानों सही क्रम में नहीं हैं, तो मैं करने के लिए अपने पृष्ठ संख्या के लिए प्रत्येक पृष्ठ scraping में देख रहा हूँ उस क्रम को निर्धारित करें जिसमें इसे जाना चाहिए (उदाहरण के लिए यदि कोई पुस्तक 20 10 पेज पीडीएफ में विभाजित करता है और मैं उन्हें एक साथ वापस रखना चाहता हूं)।pyPDF

मेरे पास दो प्रश्न हैं - 1.) मुझे पता है कि कभी-कभी पृष्ठ संख्या दस्तावेज़ डेटा में कहीं भी संग्रहीत होती है, क्योंकि मैंने पीडीएफ को देखा है जो Adobe पर कुछ [1243] (150 में से 10) जैसा प्रस्तुत करता है, लेकिन मैंने इस प्रकार के दस्तावेजों को पीईपीडीएफ में पढ़ा है और मुझे पेज नंबर इंगित करने वाली कोई जानकारी नहीं मिल रही है - यह कहां संग्रहीत है?

2.) यदि एवेन्यू # 1 उपलब्ध नहीं है, तो मुझे लगता है कि मैं किसी दिए गए पृष्ठ पर ऑब्जेक्ट्स के माध्यम से पेज नंबर खोजने का प्रयास करने के लिए पुन: प्रयास कर सकता हूं - शायद यह उसकी अपनी वस्तु होगी जिसमें इसकी एक संख्या होगी । हालांकि, मुझे वस्तुओं की सामग्री निर्धारित करने के लिए कोई स्पष्ट तरीका नहीं दिख रहा है। या तो रिटर्न

pdf.getPage(0).getContents() 

यह आमतौर पर: अगर मैं चलाने

{'/Filter': '/FlateDecode'} 

या यह IndirectObject (संख्या, संख्या) वस्तुओं की एक सूची देता है। मुझे वास्तव में पता नहीं है कि इनमें से किसी के साथ क्या करना है और जहां तक ​​मैं कह सकता हूं उस पर कोई वास्तविक दस्तावेज नहीं है। क्या कोई इस तरह की चीज से परिचित है जो मुझे सही दिशा में इंगित कर सकता है?

उत्तर

6

पूर्ण प्रलेखन के लिए, एडोब के 978 पन्ने की PDF Reference देखते हैं। :-)

अधिक विशेष रूप से, पीडीएफ फाइल मेटाडाटा इंगित करती है कि पीडीएफ की शारीरिक पृष्ठों तार्किक पृष्ठ संख्या का उल्लेख किया जाता है और कैसे पृष्ठ संख्या स्वरूपित किया जाना चाहिए होता है। यह वह जगह है जहां आप कैनोलिक परिणामों के लिए जाते हैं। उदाहरण 2 of this page दिखाता है कि यह पीडीएफ मार्कअप में कैसा दिखता है। आपको इसे बाहर निकालना होगा, इसे पार्स करना होगा, और खुद को मैपिंग करना होगा।

PyPDF में, एक प्रारंभिक बिंदु के रूप में इस जानकारी पर प्राप्त करने के लिए, कोशिश,:

pdf.trailer["/Root"]["/PageLabels"]["/Nums"] 

वैसे, जब आप एक IndirectObject उदाहरण देखते हैं, आप अपनी getObject() विधि वास्तविक वस्तु जा रहा है पुनः प्राप्त करने के कॉल कर सकते हैं इशारा किया।

आपका विकल्प, जैसा कि आप कहते हैं, पाठ वस्तुओं की जाँच करें और यह पता लगाने की जो पृष्ठ संख्या है कोशिश करने के लिए है। आप इस के लिए पेज वस्तु की extractText() इस्तेमाल कर सकते हैं, लेकिन आप एक स्ट्रिंग वापस मिल जाएगा और उस से पृष्ठ संख्या बाहर मछली करने के लिए प्रयास करने के लिए है। (और निश्चित रूप से पृष्ठ संख्या रोमन या वर्णमाला के बजाय सांख्यिक हो सकता है, और कुछ पृष्ठों गिने नहीं जा सकता है।) इसके बजाय, कैसे extractText() वास्तव में अपना काम-PyPDF पायथन में लिखा है करता है पर एक नजर है, के बाद सभी और इसका इस्तेमाल करते हैं एक दिनचर्या के आधार के रूप में जो पृष्ठ पर प्रत्येक टेक्स्ट ऑब्जेक्ट को अलग-अलग जांचता है यह देखने के लिए कि यह पृष्ठ संख्या की तरह है या नहीं। टीओसी/इंडेक्स पृष्ठों से सावधान रहें जिनके पास बहुत सारे पेज नंबर हैं!

+0

मैंने पढ़ने की कोशिश की है, लेकिन इसका कोई उपयोग नहीं .......... क्या आप एक कार्य कोड नमूना दे सकते हैं? – dreamer

15

निम्नलिखित मेरे लिए काम किया:

from PyPDF2 import PdfFileReader 
pdf = PdfFileReader(open('path/to/file.pdf','rb')) 
pdf.getNumPages() 
+1

मुझे 'pypdf' को 'pyPdf' में बदलना था और पढ़ा गया प्रकार' rb' था। –

+7

मैंने यह भी ध्यान दिया कि यह वास्तव में उस प्रश्न का उत्तर नहीं देता है जो वह पूछ रहा था, लेकिन यह वही हुआ जो मैं खोज रहा था। (पीडीएफ में पृष्ठों की संख्या) –

+4

स्मृति लीक से बचने के लिए विवरण के साथ उपयोग करना याद रखें .... खुले ('पथ/से/file.pdf', 'आरबी') के साथ पीडीएफ: पीडीएफफ़ाइल रीडर (पीडीएफ) .getNumPages() – Taran

2

kindall द्वारा जवाब बहुत अच्छा है। हालांकि, चूंकि एक वर्किंग कोड नमूना बाद में (सपने देखने वाले) से अनुरोध किया गया था और चूंकि मुझे आज भी यही समस्या थी, इसलिए मैं कुछ नोट्स जोड़ना चाहता हूं।

  1. पीडीएफ संरचना एक समान नहीं है; ऐसी कुछ चीजें हैं जिन पर आप भरोसा कर सकते हैं, इसलिए किसी भी कामकाजी कोड नमूना हर किसी के लिए काम करने की संभावना नहीं है।एक बहुत अच्छा स्पष्टीकरण in this answer पाया जा सकता है।

  2. kindall द्वारा समझाया, आप सबसे अधिक संभावना का पता लगाने के क्या पीडीएफ आप के साथ काम कर रहे हैं की आवश्यकता होगी।

तो जैसा:

import sys 
import PyPDF2 as pyPdf 

"""Open your pdf""" 
pdf = pyPdf.PdfFileReader(open(sys.argv[1], "rb")) 

"""Explore the /PageLabels (if it exists)""" 

try: 
    page_label_type = pdf.trailer["/Root"]["/PageLabels"] 
    print(page_label_type) 
except: 
    print("No /PageLabel object") 

"""Select the item that is most likely to contain the information you desire; e.g. 
     {'/Nums': [0, IndirectObject(42, 0)]} 
    here, we only have "/Num". """ 

try: 
    page_label_type = pdf.trailer["/Root"]["/PageLabels"]["/Nums"] 
    print(page_label_type) 
except: 
    print("No /PageLabel object") 

"""If you see a list, like 
     [0, IndirectObject(42, 0)] 
    get the correct item from it""" 

try: 
    page_label_type = pdf.trailer["/Root"]["/PageLabels"]["/Nums"][1] 
    print(page_label_type) 
except: 
    print("No /PageLabel object") 

"""If you then have an indirect object, like 
     IndirectObject(42, 0) 
    use getObject()""" 

try: 
    page_label_type = pdf.trailer["/Root"]["/PageLabels"]["/Nums"][1].getObject() 
    print(page_label_type) 
except: 
    print("No /PageLabel object") 

"""Now we have e.g. 
     {'/S': '/r', '/St': 21} 
    meaning roman numerals, starting with page 21, i.e. xxi. We can now also obtain the two variables directly.""" 

try: 
    page_label_type = pdf.trailer["/Root"]["/PageLabels"]["/Nums"][1].getObject()["/S"] 
    print(page_label_type) 
    start_page = pdf.trailer["/Root"]["/PageLabels"]["/Nums"][1].getObject()["/St"] 
    print(start_page) 
except: 
    print("No /PageLabel object") 
  1. आप आईएसओ पीडीएफ 1.7 विनिर्देश (प्रासंगिक अनुभाग here) से देख सकते हैं वहाँ कैसे लेबल करने की संभावनाओं के बहुत सारे कर रहे हैं पृष्ठों की है।

स्क्रिप्ट::

import sys 
import PyPDF2 as pyPdf 

def arabic_to_roman(arabic): 
    roman = '' 
    while arabic >= 1000: 
     roman += 'm' 
     arabic -= 1000 
    diffs = [900, 500, 400, 300, 200, 100, 90, 50, 40, 30, 20, 10, 9, 5, 4, 3, 2, 1] 
    digits = ['cm', 'd', 'cd', 'ccc', 'cc', 'c', 'xc', 'l', 'xl', 'xxx', 'xx', 'x', 'ix', 'v', 'iv', 'iii', 'ii', 'i'] 
    for i in range(len(diffs)): 
     if arabic >= diffs[i]: 
     roman += digits[i] 
     arabic -= diffs[i] 
    return(roman) 

def get_page_labels(pdf): 
    try: 
     page_label_type = pdf.trailer["/Root"]["/PageLabels"]["/Nums"][1].getObject()["/S"] 
    except: 
     page_label_type = "/D" 
    try: 
     page_start = pdf.trailer["/Root"]["/PageLabels"]["/Nums"][1].getObject()["/St"] 
    except: 
     page_start = 1 
    page_count = pdf.getNumPages() 
    ##or, if you feel fancy, do: 
    #page_count = pdf.trailer["/Root"]["/Pages"]["/Count"] 
    page_stop = page_start + page_count 

    if page_label_type == "/D": 
     page_numbers = list(range(page_start, page_stop)) 
     for i in range(len(page_numbers)): 
      page_numbers[i] = str(page_numbers[i]) 
    elif page_label_type == '/r': 
     page_numbers_arabic = range(page_start, page_stop) 
     page_numbers = [] 
     for i in range(len(page_numbers_arabic)): 
      page_numbers.append(arabic_to_roman(page_numbers_arabic[i])) 

    print(page_label_type) 
    print(page_start) 
    print(page_count) 
    print(page_numbers) 

pdf = pyPdf.PdfFileReader(open(sys.argv[1], "rb")) 
get_page_labels(pdf) 
1

अन्य उत्तर का उपयोग PyPDF/PyPDF2 जो लगता है पढ़ने के लिए एक सरल काम कर उदाहरण के रूप में इस स्क्रिप्ट कि दशमलव (अरबी) के साथ और रोमन अंकों के साथ कम से कम समझौते पर विचार पूरी फाइल बड़ी फ़ाइलों के लिए यह एक लंबा समय लगता है।

इस बीच में मैं त्वरित और गंदी जो कुछ चलाने के लिए लगभग के रूप में अधिक समय नहीं लगता लिखा था। यह एक खोल कॉल करता है लेकिन मुझे ऐसा करने के किसी अन्य तरीके से अवगत नहीं था। यह पीडीएफ के लिए पृष्ठों की संख्या प्राप्त कर सकता है जो ~ 5000 पेज बहुत जल्दी हैं।

यह सिर्फ "pdfinfo" शेल कमांड बुला, तो यह शायद केवल लिनक्स में काम करता है काम करता है। मैंने अभी तक उबंटू पर इसका परीक्षण किया है।

एक अजीब व्यवहार मैंने देखा है एक कोशिश में यह आसपास के/छोड़कर ब्लॉक त्रुटियां पकड़ नहीं है, आप subprocess.CalledProcessError सिवाय करना है।

from subprocess import check_output 
def get_num_pages(pdf_path): 
    output = check_output(["pdfinfo", pdf_path]).decode() 
    pages_line = [line for line in output.splitlines() if "Pages:" in line][0] 
    num_pages = int(pages_line.split(":")[1]) 
    return num_pages 
+0

बस एहसास हुआ कि सवाल विशेष रूप से पीपीडीएफएफ के लिए था, लेकिन यह पहला परिणाम है जब पीईएफएफ में पीडीएफ में पृष्ठों की संख्या कैसे प्राप्त करें, तो यह जवाब सबसे अधिक प्रासंगिक होगा। –