โมดูล Python สำหรับแปลง PDF เป็นข้อความ [ปิด]


385

มีโมดูลหลามแปลงไฟล์ PDF เป็นข้อความหรือไม่? ฉันลองใช้รหัสหนึ่งชิ้นที่พบใน Activestate ซึ่งใช้ pypdf แต่ข้อความที่สร้างขึ้นไม่มีช่องว่างระหว่างและไม่มีประโยชน์


1
ฉันกำลังมองหาวิธีการแก้ปัญหาที่คล้ายกัน ฉันแค่ต้องอ่านข้อความจากไฟล์ pdf ฉันไม่ต้องการรูปภาพ pdfminer เป็นตัวเลือกที่ดี แต่ฉันไม่พบตัวอย่างง่ายๆเกี่ยวกับวิธีแยกข้อความ ในที่สุดฉันก็ได้คำตอบดังนั้น ( stackoverflow.com/questions/5725278/… ) และตอนนี้ใช้มัน
Nayan

2
ตั้งแต่คำถามถูกปิดฉันโพสต์ใหม่ใน Stack Exchange ที่อุทิศให้กับคำแนะนำซอฟต์แวร์ในกรณีที่มีคนต้องการเขียนคำตอบใหม่: โมดูล Python สำหรับการแปลง PDF เป็นข้อความ
Franck Dernoncourt

1
ทางออกเดียวที่ทำงานสำหรับฉันสำหรับเนื้อหา UTF-8: Apache Tika
Shoham

ฉันต้องการอัปเดตรายการตัวเลือกที่มีสำหรับการแปลง PDF เป็นข้อความใน Python, GroupDocs.Conversion Cloud SDK สำหรับ Pythonแปลง PDF เป็นข้อความอย่างถูกต้อง
Tilal Ahmad

คำตอบ:


142

ลองPDFMiner มันสามารถแยกข้อความจากไฟล์ PDF เป็นรูปแบบ HTML, SGML หรือ "Tagged PDF"

รูปแบบ PDF ที่ติดแท็กดูเหมือนจะสะอาดที่สุดและการแยกแท็ก XML ออกจากข้อความเปล่าเท่านั้น

เวอร์ชัน Python 3 มีให้ใน:


2
ฉันเพิ่งเพิ่มคำตอบวิธีการใช้ pdfminer เป็นห้องสมุด
codeape

24
ไม่มีการสนับสนุน python 3 :(
Karl Adler

1
คำตอบที่ฉันให้ไว้ในหัวข้อนี้อาจเป็นประโยชน์สำหรับผู้ที่ดูคำตอบนี้และสงสัยว่าจะใช้ห้องสมุดอย่างไร ฉันยกตัวอย่างวิธีใช้ไลบรารี PDFMiner เพื่อแยกข้อความจาก PDF เนื่องจากเอกสารนั้นค่อนข้างกระจัดกระจายฉันจึงคิดว่าอาจช่วยคนจำนวนน้อยได้
DuckPuncher

17
เกี่ยวกับงูหลาม 3 มีทางแยกหกตามpypi.python.org/pypi/pdfminer.six
เดนิส Cornehl

1
โค้ดตัวอย่างที่stackoverflow.com/a/26495057/125617
Renaud

136

PDFMinerแพคเกจมีการเปลี่ยนแปลงตั้งแต่codeapeโพสต์

แก้ไข (อีกครั้ง):

PDFMiner ได้รับการอัปเดตอีกครั้งในเวอร์ชัน 20100213

คุณสามารถตรวจสอบเวอร์ชั่นที่คุณติดตั้งด้วยดังต่อไปนี้:

>>> import pdfminer
>>> pdfminer.__version__
'20100213'

นี่คือเวอร์ชันที่อัปเดต (พร้อมความคิดเห็นเกี่ยวกับสิ่งที่ฉันเปลี่ยน / เพิ่ม):

def pdf_to_csv(filename):
    from cStringIO import StringIO  #<-- added so you can copy/paste this to try it
    from pdfminer.converter import LTTextItem, TextConverter
    from pdfminer.pdfparser import PDFDocument, PDFParser
    from pdfminer.pdfinterp import PDFResourceManager, PDFPageInterpreter

    class CsvConverter(TextConverter):
        def __init__(self, *args, **kwargs):
            TextConverter.__init__(self, *args, **kwargs)

        def end_page(self, i):
            from collections import defaultdict
            lines = defaultdict(lambda : {})
            for child in self.cur_item.objs:
                if isinstance(child, LTTextItem):
                    (_,_,x,y) = child.bbox                   #<-- changed
                    line = lines[int(-y)]
                    line[x] = child.text.encode(self.codec)  #<-- changed

            for y in sorted(lines.keys()):
                line = lines[y]
                self.outfp.write(";".join(line[x] for x in sorted(line.keys())))
                self.outfp.write("\n")

    # ... the following part of the code is a remix of the 
    # convert() function in the pdfminer/tools/pdf2text module
    rsrc = PDFResourceManager()
    outfp = StringIO()
    device = CsvConverter(rsrc, outfp, codec="utf-8")  #<-- changed 
        # becuase my test documents are utf-8 (note: utf-8 is the default codec)

    doc = PDFDocument()
    fp = open(filename, 'rb')
    parser = PDFParser(fp)       #<-- changed
    parser.set_document(doc)     #<-- added
    doc.set_parser(parser)       #<-- added
    doc.initialize('')

    interpreter = PDFPageInterpreter(rsrc, device)

    for i, page in enumerate(doc.get_pages()):
        outfp.write("START PAGE %d\n" % i)
        interpreter.process_page(page)
        outfp.write("END PAGE %d\n" % i)

    device.close()
    fp.close()

    return outfp.getvalue()

แก้ไข (ยังอีกครั้ง):

นี่คือการปรับปรุงสำหรับรุ่นล่าสุดในpypi20100619p1 , ในระยะสั้นฉันแทนที่LTTextItemด้วยLTCharและส่งตัวอย่างของ LAParams ไปยัง CsvConverter Constructor

def pdf_to_csv(filename):
    from cStringIO import StringIO  
    from pdfminer.converter import LTChar, TextConverter    #<-- changed
    from pdfminer.layout import LAParams
    from pdfminer.pdfparser import PDFDocument, PDFParser
    from pdfminer.pdfinterp import PDFResourceManager, PDFPageInterpreter

    class CsvConverter(TextConverter):
        def __init__(self, *args, **kwargs):
            TextConverter.__init__(self, *args, **kwargs)

        def end_page(self, i):
            from collections import defaultdict
            lines = defaultdict(lambda : {})
            for child in self.cur_item.objs:
                if isinstance(child, LTChar):               #<-- changed
                    (_,_,x,y) = child.bbox                   
                    line = lines[int(-y)]
                    line[x] = child.text.encode(self.codec)

            for y in sorted(lines.keys()):
                line = lines[y]
                self.outfp.write(";".join(line[x] for x in sorted(line.keys())))
                self.outfp.write("\n")

    # ... the following part of the code is a remix of the 
    # convert() function in the pdfminer/tools/pdf2text module
    rsrc = PDFResourceManager()
    outfp = StringIO()
    device = CsvConverter(rsrc, outfp, codec="utf-8", laparams=LAParams())  #<-- changed
        # becuase my test documents are utf-8 (note: utf-8 is the default codec)

    doc = PDFDocument()
    fp = open(filename, 'rb')
    parser = PDFParser(fp)       
    parser.set_document(doc)     
    doc.set_parser(parser)       
    doc.initialize('')

    interpreter = PDFPageInterpreter(rsrc, device)

    for i, page in enumerate(doc.get_pages()):
        outfp.write("START PAGE %d\n" % i)
        if page is not None:
            interpreter.process_page(page)
        outfp.write("END PAGE %d\n" % i)

    device.close()
    fp.close()

    return outfp.getvalue()

แก้ไข (อีกครั้ง):

อัปเดตสำหรับรุ่น20110515(ขอบคุณ Oeufcoque Penteano!):

def pdf_to_csv(filename):
    from cStringIO import StringIO  
    from pdfminer.converter import LTChar, TextConverter
    from pdfminer.layout import LAParams
    from pdfminer.pdfparser import PDFDocument, PDFParser
    from pdfminer.pdfinterp import PDFResourceManager, PDFPageInterpreter

    class CsvConverter(TextConverter):
        def __init__(self, *args, **kwargs):
            TextConverter.__init__(self, *args, **kwargs)

        def end_page(self, i):
            from collections import defaultdict
            lines = defaultdict(lambda : {})
            for child in self.cur_item._objs:                #<-- changed
                if isinstance(child, LTChar):
                    (_,_,x,y) = child.bbox                   
                    line = lines[int(-y)]
                    line[x] = child._text.encode(self.codec) #<-- changed

            for y in sorted(lines.keys()):
                line = lines[y]
                self.outfp.write(";".join(line[x] for x in sorted(line.keys())))
                self.outfp.write("\n")

    # ... the following part of the code is a remix of the 
    # convert() function in the pdfminer/tools/pdf2text module
    rsrc = PDFResourceManager()
    outfp = StringIO()
    device = CsvConverter(rsrc, outfp, codec="utf-8", laparams=LAParams())
        # becuase my test documents are utf-8 (note: utf-8 is the default codec)

    doc = PDFDocument()
    fp = open(filename, 'rb')
    parser = PDFParser(fp)       
    parser.set_document(doc)     
    doc.set_parser(parser)       
    doc.initialize('')

    interpreter = PDFPageInterpreter(rsrc, device)

    for i, page in enumerate(doc.get_pages()):
        outfp.write("START PAGE %d\n" % i)
        if page is not None:
            interpreter.process_page(page)
        outfp.write("END PAGE %d\n" % i)

    device.close()
    fp.close()

    return outfp.getvalue()

1
ใน [6]: import pdfminer ใน [7]: pdfminer .__ version__ ออก [7]: '20100424' ใน [8]: จาก pdfminer.converter การนำเข้า LTTextItem ImportError: ไม่สามารถนำเข้าชื่อ LTTextItem .... LITERALS_DCT_DECODE LTChar LTImage LTContainer LTLine LTRect LTTextGroup LITERAL_DEVICE_RGB LTFigure LTPage LTText LTText LTTextLTT
Skylar Saveland

@skyl รหัสข้างต้นเป็นเวอร์ชั่นก่อนหน้า '20100213' จากรายการของการเปลี่ยนแปลงบนเว็บไซต์ของพวกเขาดูเหมือนว่าพวกเขาเปลี่ยนไป LTTextItem unixuser.org/~euske/python/pdfminer/index.html#changesLTChar
tgray

2
@Oufufque Penteano ขอบคุณ! ฉันได้เพิ่มส่วนอื่นในคำตอบสำหรับเวอร์ชัน20110515ตามความคิดเห็นของคุณ
tgray

1
คำตอบที่ได้รับจาก @ user3272884 ทำงานตั้งแต่ 5-1-2014
jmunsch

1
ฉันต้องแก้ปัญหาเดียวกันนี้ในวันนี้แก้ไขโค้ดของ tgray สักหน่อยเพื่อดึงข้อมูลเกี่ยวกับช่องว่าง, โพสต์ไว้ที่นี่
tarikki

67

เนื่องจากไม่มีโซลูชันเหล่านี้รองรับ PDFMiner เวอร์ชันล่าสุดฉันจึงเขียนโซลูชันง่าย ๆ ที่จะส่งคืนข้อความของ PDF โดยใช้ PDFMiner วิธีนี้จะทำงานสำหรับผู้ที่ได้รับข้อผิดพลาดในการนำเข้าด้วยprocess_pdf

import sys
from pdfminer.pdfinterp import PDFResourceManager, PDFPageInterpreter
from pdfminer.pdfpage import PDFPage
from pdfminer.converter import XMLConverter, HTMLConverter, TextConverter
from pdfminer.layout import LAParams
from cStringIO import StringIO

def pdfparser(data):

    fp = file(data, 'rb')
    rsrcmgr = PDFResourceManager()
    retstr = StringIO()
    codec = 'utf-8'
    laparams = LAParams()
    device = TextConverter(rsrcmgr, retstr, codec=codec, laparams=laparams)
    # Create a PDF interpreter object.
    interpreter = PDFPageInterpreter(rsrcmgr, device)
    # Process each page contained in the document.

    for page in PDFPage.get_pages(fp):
        interpreter.process_page(page)
        data =  retstr.getvalue()

    print data

if __name__ == '__main__':
    pdfparser(sys.argv[1])  

ดูรหัสด้านล่างที่ใช้งานได้กับ Python 3:

import sys
from pdfminer.pdfinterp import PDFResourceManager, PDFPageInterpreter
from pdfminer.pdfpage import PDFPage
from pdfminer.converter import XMLConverter, HTMLConverter, TextConverter
from pdfminer.layout import LAParams
import io

def pdfparser(data):

    fp = open(data, 'rb')
    rsrcmgr = PDFResourceManager()
    retstr = io.StringIO()
    codec = 'utf-8'
    laparams = LAParams()
    device = TextConverter(rsrcmgr, retstr, codec=codec, laparams=laparams)
    # Create a PDF interpreter object.
    interpreter = PDFPageInterpreter(rsrcmgr, device)
    # Process each page contained in the document.

    for page in PDFPage.get_pages(fp):
        interpreter.process_page(page)
        data =  retstr.getvalue()

    print(data)

if __name__ == '__main__':
    pdfparser(sys.argv[1])  

2
นี่เป็นตัวอย่างแรกที่ฉันพบว่าใช้งานได้จริงกับไฟล์ PDF แปลก ๆ (โดยเฉพาะ ebooks ฟรีที่สามารถรับได้จาก packtpub) โค้ดอื่น ๆ ทุกชิ้นจะส่งคืนข้อมูลดิบที่เข้ารหัสอย่างประหลาด แต่จริง ๆ แล้วคุณจะได้รับข้อความ ขอบคุณ!
somada141

คุณอาจต้องการทำ retstr.seek (0) หลังจากรับข้อมูลหรือคุณจะรวบรวมข้อความจากทุกหน้า
Tshirtman

2
หากต้องการใช้กับpython3นอกเหนือจากวงเล็บที่ชัดเจนหลังprintคำสั่งเราจะต้องแทนที่fileคำสั่งด้วยopenและนำเข้าStringIOจากแพ็คเกจio
McLawrence

1
ว้าว. บล็อกนี้ทำงานได้อย่างสมบูรณ์ในครั้งแรกเมื่อฉันคัดลอกมาน่าทึ่ง! ไปที่การแยกวิเคราะห์และแก้ไขข้อมูลและไม่ต้องเครียดกับการป้อนข้อมูล
SecsAndCyber

1
pdfminer ใช้งานไม่ได้กับ python3 รหัสนี้ไม่ทำงานสำหรับ pdfminer3k
Thang

47

Pdftotextโปรแกรมโอเพนซอร์ซ (ส่วนหนึ่งของ Xpdf) ซึ่งคุณสามารถโทรจากไพ ธ อน (ไม่ใช่สิ่งที่คุณขอ แต่อาจมีประโยชน์) ฉันใช้มันโดยไม่มีปัญหา ฉันคิดว่า google ใช้มันใน google desktop


6
สิ่งนี้ดูเหมือนจะเป็นเครื่องมือที่มีประโยชน์มากที่สุดที่ระบุไว้ที่นี่พร้อม-layoutตัวเลือกในการเก็บข้อความในตำแหน่งเดียวกับที่อยู่ในรูปแบบ PDF ตอนนี้ถ้าเพียงฉันสามารถหาวิธีการไพพ์เนื้อหาของ PDF ลงไปได้
Matthew Schinckel

หลังจากทดสอบวิธีแก้ปัญหาต่าง ๆ แล้วอันนี้ก็ดูเหมือนจะเป็นทางเลือกที่ง่ายและแข็งแกร่งที่สุด สามารถห่อด้วย Python ได้อย่างง่ายดายโดยใช้ tempfile เพื่อกำหนดว่าเอาต์พุตจะถูกเขียนไปที่ใด
Cerin

Cerinใช้ '-' เป็นชื่อไฟล์เพื่อเปลี่ยนเส้นทางเอาต์พุตไปยัง stdout วิธีนี้คุณสามารถใช้งาน subprocess.check_output อย่างง่ายและการโทรนี้จะรู้สึกเหมือนฟังก์ชั่นภายใน
Ctrl-C

เพียงแค่บังคับใช้ใครก็ตามที่ใช้งานอีกครั้ง . . pdftotextดูเหมือนว่าจะทำงานได้ดี แต่ต้องการอาร์กิวเมนต์ที่สองที่เป็นยัติภังค์หากคุณต้องการดูผลลัพธ์ใน stdout
Gordon Linoff

1
การดำเนินการนี้จะแปลงไฟล์ PDF ทั้งหมดที่เริ่มต้นจากโฟลเดอร์ปัจจุบันซ้ำ: find . -iname "*.pdf" -exec pdftotext -enc UTF-8 -eol unix -raw {} \;ตามค่าเริ่มต้นไฟล์ที่สร้างขึ้นจะใช้ชื่อเดิมพร้อม.txtนามสกุล
ccpizza

43

pyPDFทำงานได้ดี (สมมติว่าคุณทำงานกับ PDF ที่มีรูปแบบถูกต้อง) หากสิ่งที่คุณต้องการคือข้อความ (มีช่องว่าง) คุณสามารถทำได้:

import pyPdf
pdf = pyPdf.PdfFileReader(open(filename, "rb"))
for page in pdf.pages:
    print page.extractText()

คุณสามารถเข้าถึงข้อมูลเมตาข้อมูลภาพและอื่น ๆ ได้อย่างง่ายดาย

ความคิดเห็นในหมายเหตุโค้ด extractText:

ค้นหาคำสั่งการวาดข้อความทั้งหมดตามลำดับที่ให้ไว้ในสตรีมเนื้อหาและแยกข้อความ สิ่งนี้ทำงานได้ดีสำหรับไฟล์ PDF บางไฟล์ แต่ไม่ดีสำหรับไฟล์อื่นขึ้นอยู่กับตัวสร้างที่ใช้ สิ่งนี้จะได้รับการปรับปรุงในอนาคต อย่าพึ่งพาลำดับของข้อความที่ออกมาจากฟังก์ชั่นนี้เนื่องจากมันจะเปลี่ยนไปถ้าฟังก์ชั่นนี้มีความซับซ้อนมากขึ้น

ไม่ว่าจะเป็นปัญหาหรือไม่ขึ้นอยู่กับสิ่งที่คุณกำลังทำกับข้อความ (เช่นถ้าคำสั่งไม่สำคัญก็ดีหรือถ้าเครื่องกำเนิดไฟฟ้าเพิ่มข้อความในสตรีมตามลำดับที่จะแสดงก็ไม่เป็นไร) . ฉันมีรหัสการแยก pyPdf ในการใช้งานทุกวันโดยไม่มีปัญหาใด ๆ


7
ไม่มีการสนับสนุน unicode :(
PanosJee

7
pyPdf รองรับ UTF ทันที
lbolla

2
ห้องสมุดนี้ดูเหมือนขยะ การทดสอบ PDF แบบสุ่มทำให้ฉันมีข้อผิดพลาด "pyPdf.utils.PdfReadError: ไม่พบตัวทำเครื่องหมาย EOF"
Cerin

4
จากคำถาม: ข้อความที่สร้างขึ้นมีช่องว่างระหว่างไม่มีและไม่มีประโยชน์ ฉันใช้ pyPDF และได้ผลลัพธ์เดียวกัน - แยกข้อความโดยไม่มีช่องว่างระหว่างคำ
Jordan Reiter

เมื่อฉันเรียกใช้ฟังก์ชัน page.extractText () ฉันได้รับข้อผิดพลาด 'TypeError: ไม่สามารถแปลงวัตถุ' ไบต์ 'เป็น str โดยปริยาย' ฉันจะจัดการกับสิ่งนั้นได้อย่างไร
juankysmith

21

คุณยังสามารถใช้ pdfminer เป็นห้องสมุดได้อย่างง่ายดาย คุณสามารถเข้าถึงรูปแบบเนื้อหาของ pdf และสามารถสร้างการแยกข้อความของคุณเอง ฉันทำสิ่งนี้เพื่อแปลงเนื้อหา pdf เป็นข้อความคั่นด้วยเครื่องหมายอัฒภาคโดยใช้โค้ดด้านล่าง

ฟังก์ชั่นจะเรียงลำดับวัตถุเนื้อหา TextItem ตามพิกัด y และ x ของพวกเขาและแสดงรายการด้วยพิกัด y เดียวกันกับบรรทัดข้อความเดียวโดยแยกวัตถุในบรรทัดเดียวกันด้วย ';' ตัวละคร

การใช้วิธีการนี้ทำให้ฉันสามารถดึงข้อความจาก pdf ที่ไม่มีเครื่องมืออื่นที่สามารถแยกเนื้อหาที่เหมาะสมสำหรับการแยกวิเคราะห์เพิ่มเติมได้ เครื่องมืออื่น ๆ ที่ฉันลองใช้รวมถึง pdftotext, ps2ascii และเครื่องมือออนไลน์ pdftextonline.com

pdfminer เป็นเครื่องมือที่มีค่าสำหรับการคัดลอก PDF


def pdf_to_csv(filename):
    from pdflib.page import TextItem, TextConverter
    from pdflib.pdfparser import PDFDocument, PDFParser
    from pdflib.pdfinterp import PDFResourceManager, PDFPageInterpreter

    class CsvConverter(TextConverter):
        def __init__(self, *args, **kwargs):
            TextConverter.__init__(self, *args, **kwargs)

        def end_page(self, i):
            from collections import defaultdict
            lines = defaultdict(lambda : {})
            for child in self.cur_item.objs:
                if isinstance(child, TextItem):
                    (_,_,x,y) = child.bbox
                    line = lines[int(-y)]
                    line[x] = child.text

            for y in sorted(lines.keys()):
                line = lines[y]
                self.outfp.write(";".join(line[x] for x in sorted(line.keys())))
                self.outfp.write("\n")

    # ... the following part of the code is a remix of the 
    # convert() function in the pdfminer/tools/pdf2text module
    rsrc = PDFResourceManager()
    outfp = StringIO()
    device = CsvConverter(rsrc, outfp, "ascii")

    doc = PDFDocument()
    fp = open(filename, 'rb')
    parser = PDFParser(doc, fp)
    doc.initialize('')

    interpreter = PDFPageInterpreter(rsrc, device)

    for i, page in enumerate(doc.get_pages()):
        outfp.write("START PAGE %d\n" % i)
        interpreter.process_page(page)
        outfp.write("END PAGE %d\n" % i)

    device.close()
    fp.close()

    return outfp.getvalue()

อัปเดต :

รหัสด้านบนเขียนขึ้นจาก API เวอร์ชันเก่าดูความคิดเห็นของฉันด้านล่าง


คุณต้องการปลั๊กอินชนิดใดเพื่อใช้ในการทำงานกับเพื่อน ฉันดาวน์โหลดและติดตั้ง pdfminer แล้ว แต่ยังไม่พอ ...
kxk

1
รหัสข้างต้นเขียนขึ้นจากโปรแกรม PDFminer รุ่นเก่า API มีการเปลี่ยนแปลงในเวอร์ชันที่ใหม่กว่า (ตัวอย่างเช่นแพ็คเกจนี้pdfminerไม่ใช่pdflib) ฉันขอแนะนำให้คุณดูที่แหล่งที่มาของแหล่งpdf2txt.pyPDFminer โค้ดข้างต้นได้รับแรงบันดาลใจจากไฟล์เวอร์ชันเก่า
codeape

17

slate เป็นโครงการที่ทำให้การใช้ PDFMiner นั้นง่ายมากจากไลบรารี:

>>> with open('example.pdf') as f:
...    doc = slate.PDF(f)
...
>>> doc
[..., ..., ...]
>>> doc[1]
'Text from page 2...'   

1
ฉันได้รับข้อผิดพลาดในการนำเข้าขณะดำเนินการ "import slate": {File "C: \ Python33 \ lib \ site-packages \ slate-0.3-py3.3.egg \ slate_ init_ .py ", บรรทัดที่ 48 ใน <module> ImportError: ไม่สามารถนำเข้าชื่อ PDF} แต่มีคลาส PDF อยู่ที่นั่น! คุณรู้วิธีแก้ปัญหานี้หรือไม่?
juankysmith

ไม่ฟังดูแปลกมาก คุณมีการพึ่งพาหรือไม่
Tim McNamara

โดยปกติฉันได้รับข้อความเกี่ยวกับการขึ้นต่อกันที่ไม่ได้รับในกรณีนี้ฉันได้รับข้อความคลาสสิค "import slate File" C: \ Python33 \ lib \ site-packages \ slate-0.3-py3.3.egg \ slate_ init_ .py ", บรรทัดที่ 48 ใน <module> ImportError: ไม่สามารถนำเข้าชื่อ PDF "
juankysmith

Slate 0.3 ต้องใช้ pdfminer 20110515 ตามปัญหา GitHub นี้
jabbett

6
แพ็คเกจนี้ไม่ได้รับการดูแลอีกต่อไป หลีกเลี่ยงการใช้งาน คุณไม่สามารถใช้งานได้ใน Python 3.5
Sivasubramaniam Arunachalam

9

ฉันต้องการแปลง PDF เฉพาะเป็นข้อความธรรมดาภายในโมดูลหลาม ฉันใช้PDFMiner 20110515 หลังจากอ่านเครื่องมือpdf2txt.pyของพวกเขาฉันเขียนตัวอย่างง่ายๆนี้:

from cStringIO import StringIO
from pdfminer.pdfinterp import PDFResourceManager, process_pdf
from pdfminer.converter import TextConverter
from pdfminer.layout import LAParams

def to_txt(pdf_path):
    input_ = file(pdf_path, 'rb')
    output = StringIO()

    manager = PDFResourceManager()
    converter = TextConverter(manager, output, laparams=LAParams())
    process_pdf(manager, converter, input_)

    return output.getvalue() 

1
def to_txt (pdf_path):
Cătălin George Feștilă

ถ้าฉันต้องการแปลงเฉพาะบางหน้าฉันจะทำอย่างไรกับรหัสนี้?
psychok7

@ psychok7 คุณลองใช้เครื่องมือ pdf2txt หรือยัง ดูเหมือนว่าจะสนับสนุนคุณสมบัตินั้นในเวอร์ชันปัจจุบันด้วยแฟล็ก -p การใช้งานดูเหมือนง่ายต่อการติดตามและควรปรับแต่งได้ง่ายเช่นกัน: github.com/euske/pdfminer/blob/master/tools/pdf2txt.pyหวังว่ามันจะช่วยได้! :)
gonz

1
ขอบคุณ @gonz ผมพยายามทั้งหมดข้างต้น แต่วิธีการแก้ปัญหาของคุณจะเปิดออกจะสมบูรณ์แบบสำหรับผม ,, เอาท์พุทที่มีช่องว่าง :)
ลาซารัส

pdf2txt.py ติดตั้งไว้ที่นี่สำหรับฉัน:C:\Python27\Scripts\pdfminer\tools\pdf2txt.py
Red Pea

6

การนำเสนอโค้ด pdf2txt.py อีกครั้งที่มาพร้อมกับ pdfminer คุณสามารถสร้างฟังก์ชั่นที่จะพาไปยังไฟล์ pdf; เป็นตัวเลือก outtype (txt | html | xml | tag) และ opts เช่น commandline pdf2txt {'-o': '/path/to/outfile.txt' ... } โดยค่าเริ่มต้นคุณสามารถโทร:

convert_pdf(path)

ไฟล์ข้อความจะถูกสร้างขึ้นซึ่งเป็นพี่น้องในระบบไฟล์กับไฟล์ PDF ต้นฉบับ

def convert_pdf(path, outtype='txt', opts={}):
    import sys
    from pdfminer.pdfinterp import PDFResourceManager, PDFPageInterpreter, process_pdf
    from pdfminer.converter import XMLConverter, HTMLConverter, TextConverter, TagExtractor
    from pdfminer.layout import LAParams
    from pdfminer.pdfparser import PDFDocument, PDFParser
    from pdfminer.pdfdevice import PDFDevice
    from pdfminer.cmapdb import CMapDB

    outfile = path[:-3] + outtype
    outdir = '/'.join(path.split('/')[:-1])

    debug = 0
    # input option
    password = ''
    pagenos = set()
    maxpages = 0
    # output option
    codec = 'utf-8'
    pageno = 1
    scale = 1
    showpageno = True
    laparams = LAParams()
    for (k, v) in opts:
        if k == '-d': debug += 1
        elif k == '-p': pagenos.update( int(x)-1 for x in v.split(',') )
        elif k == '-m': maxpages = int(v)
        elif k == '-P': password = v
        elif k == '-o': outfile = v
        elif k == '-n': laparams = None
        elif k == '-A': laparams.all_texts = True
        elif k == '-D': laparams.writing_mode = v
        elif k == '-M': laparams.char_margin = float(v)
        elif k == '-L': laparams.line_margin = float(v)
        elif k == '-W': laparams.word_margin = float(v)
        elif k == '-O': outdir = v
        elif k == '-t': outtype = v
        elif k == '-c': codec = v
        elif k == '-s': scale = float(v)
    #
    CMapDB.debug = debug
    PDFResourceManager.debug = debug
    PDFDocument.debug = debug
    PDFParser.debug = debug
    PDFPageInterpreter.debug = debug
    PDFDevice.debug = debug
    #
    rsrcmgr = PDFResourceManager()
    if not outtype:
        outtype = 'txt'
        if outfile:
            if outfile.endswith('.htm') or outfile.endswith('.html'):
                outtype = 'html'
            elif outfile.endswith('.xml'):
                outtype = 'xml'
            elif outfile.endswith('.tag'):
                outtype = 'tag'
    if outfile:
        outfp = file(outfile, 'w')
    else:
        outfp = sys.stdout
    if outtype == 'txt':
        device = TextConverter(rsrcmgr, outfp, codec=codec, laparams=laparams)
    elif outtype == 'xml':
        device = XMLConverter(rsrcmgr, outfp, codec=codec, laparams=laparams, outdir=outdir)
    elif outtype == 'html':
        device = HTMLConverter(rsrcmgr, outfp, codec=codec, scale=scale, laparams=laparams, outdir=outdir)
    elif outtype == 'tag':
        device = TagExtractor(rsrcmgr, outfp, codec=codec)
    else:
        return usage()

    fp = file(path, 'rb')
    process_pdf(rsrcmgr, device, fp, pagenos, maxpages=maxpages, password=password)
    fp.close()
    device.close()

    outfp.close()
    return

1

PDF อาจให้ฉันหนึ่งบรรทัด [หน้า 1 จาก 7 ... ] ในทุกหน้าของไฟล์ PDF ที่ฉันลองด้วย

คำตอบที่ดีที่สุดที่ฉันมีคือ pdftoipe หรือรหัส c ++ ตาม Xpdf

ดูคำถามของฉันสำหรับสิ่งที่ผลลัพธ์ของ pdftoipe ดูเหมือน



1

ฉันได้ใช้pdftohtmlกับ-xmlอาร์กิวเมนต์อ่านผลด้วยsubprocess.Popen()ที่จะทำให้คุณ x COORD, COORD Y, ความกว้างความสูงและตัวอักษรของทุกข้อมูลโค้ดของข้อความในรูปแบบไฟล์ PDF ฉันคิดว่านี่เป็นสิ่งที่ 'evince' อาจใช้เช่นกันเนื่องจากข้อความแสดงข้อผิดพลาดเดียวกันพ่นออกมา

หากคุณต้องการประมวลผลข้อมูลเรียงเป็นแนวมันจะซับซ้อนกว่าเล็กน้อยเนื่องจากคุณต้องคิดค้นอัลกอริทึมที่เหมาะกับไฟล์ pdf ของคุณ ปัญหาคือโปรแกรมที่สร้างไฟล์ PDF นั้นไม่จำเป็นต้องจัดวางข้อความในรูปแบบโลจิคัลใด ๆ คุณสามารถลองใช้อัลกอริธึมการเรียงลำดับแบบง่าย ๆ ได้และบางครั้งก็ใช้งานได้ แต่อาจมี 'พลัดหลง' และ 'หลงทาง' ชิ้นส่วนของข้อความที่ไม่เรียงตามลำดับที่คุณคิด ดังนั้นคุณต้องมีความคิดสร้างสรรค์

ฉันใช้เวลาประมาณ 5 ชั่วโมงกว่าจะคิดออกหนึ่งไฟล์สำหรับไฟล์ pdf ที่ฉันใช้งานอยู่ แต่ตอนนี้มันใช้งานได้ดีมาก โชคดี.


โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.