Mengekstrak teks dari file PDF menggunakan PDFMiner dengan python?

89

Saya mencari dokumentasi atau contoh bagaimana mengekstrak teks dari file PDF menggunakan PDFMiner dengan Python.

Sepertinya PDFMiner memperbarui API mereka dan semua contoh relevan yang saya temukan berisi kode usang (kelas dan metode telah berubah). Pustaka yang saya temukan yang membuat tugas mengekstrak teks dari file PDF lebih mudah menggunakan sintaks PDFMiner lama jadi saya tidak yakin bagaimana melakukan ini.

Karena itu, saya hanya melihat kode sumber untuk melihat apakah saya bisa mengetahuinya.

DuckPuncher
sumber
1
Harap periksa stackoverflow.com/help/how-to-ask dan stackoverflow.com/help/mcve dan perbarui jawaban Anda sehingga dalam format yang lebih baik dan sejalan dengan pedoman.
Parker
Distribusi Python mana yang Anda gunakan, 2.7.x atau 3.xx? Perlu dicatat bahwa penulis secara eksplisit merinci yang PDFminertidak bekerja dengan Python 3.xx Itu mungkin alasan Anda mendapatkan importkesalahan. Anda harus menggunakan pdfminer3kjika demikian, karena ini adalah impor Python 3 berdiri dari perpustakaan tersebut.
NullDev
@Nanashi, maaf, saya lupa menambahkan versi Python saya. Ini 2,7 jadi bukan itu masalahnya. Saya telah melihat-lihat kode sumbernya dan sepertinya mereka merestrukturisasi beberapa hal yang menyebabkan impor rusak. Saya juga tidak dapat menemukan dokumentasi untuk PDFMiner atau saya hanya akan mengerjakannya :(
DuckPuncher
Saya baru saja menginstal PDFminerdari GitHub dan mengimpor dengan baik. Bisakah Anda memposting kode dan memposting pelacakan error lengkap juga?
NullDev
@Nanashi, Seperti yang saya katakan dalam pertanyaan asli saya, perpustakaan yang mengandalkan PDFMiner berhenti sebelum menyelesaikan impor bersama dengan contoh apa pun yang dapat saya temukan. Ini bukan masalah PDFMiner. Ini saya mencari dokumentasi, atau contoh cara menggunakan PDFMiner. Semua yang dapat saya temukan menggunakan sintaks lama untuk PDFMiner. Saya melanjutkan dan mengedit pertanyaan saya untuk kejelasan. Saya pikir saya membuatnya lebih membingungkan daripada yang seharusnya. Maaf soal itu.
DuckPuncher

Jawaban:

184

Berikut adalah contoh kerja mengekstrak teks dari file PDF menggunakan versi PDFMiner saat ini (September 2016)

from pdfminer.pdfinterp import PDFResourceManager, PDFPageInterpreter
from pdfminer.converter import TextConverter
from pdfminer.layout import LAParams
from pdfminer.pdfpage import PDFPage
from io import StringIO

def convert_pdf_to_txt(path):
    rsrcmgr = PDFResourceManager()
    retstr = StringIO()
    codec = 'utf-8'
    laparams = LAParams()
    device = TextConverter(rsrcmgr, retstr, codec=codec, laparams=laparams)
    fp = open(path, 'rb')
    interpreter = PDFPageInterpreter(rsrcmgr, device)
    password = ""
    maxpages = 0
    caching = True
    pagenos=set()

    for page in PDFPage.get_pages(fp, pagenos, maxpages=maxpages, password=password,caching=caching, check_extractable=True):
        interpreter.process_page(page)

    text = retstr.getvalue()

    fp.close()
    device.close()
    retstr.close()
    return text

Struktur PDFMiner berubah baru-baru ini, jadi ini seharusnya berfungsi untuk mengekstrak teks dari file PDF.

Sunting : Masih berfungsi pada 7 Juni 2018. Diverifikasi dengan Python Versi 3.x

Sunting: Solusinya bekerja dengan Python 3.7 pada 3 Oktober 2019. Saya menggunakan perpustakaan Python pdfminer.six, dirilis pada November 2018.

DuckPuncher
sumber
2
berfungsi dengan baik, tetapi, bagaimana cara menangani spasi di misalnya nama? misalkan saya memiliki pdf yang berisi 4 kolom di mana saya memiliki nama depan dan belakang dalam satu kolom, sekarang diurai dengan nama depan dalam satu baris dan nama belakang dalam satu baris, berikut adalah contoh docdro.id/rRyef3x
Deusdeorum
2
Saat ini mendapatkan kesalahan impor dengan kode ini: ImportError: Tidak ada modul bernama 'pdfminer.pdfpage'
Jeffrey Swan
1
Terima kasih ini berfungsi pada python v2.7.12 dan ubuntu 16.04, meskipun akan lebih baik untuk memuat dokumen pdf dengan pengkodean utf-8, karena sampel pdf saya memiliki beberapa masalah pengkodean jadi coba ini setelah pengkodean dengan utf-8 dan itu menyelesaikan masalah ... import sys reload(sys) sys.setdefaultencoding('utf-8')
sib10
2
@DuckPuncher, Apakah masih berfungsi sekarang? Saya harus mengubah file(path, 'rb')menjadi `open (path, 'rb') agar milik saya berfungsi.
diambil
2
Masih berfungsi untuk pengguna Python3.7. Menginstal pdfminer.six == 20181108 paket. Solusi terbaik sejauh ini untuk kasus saya dan saya membandingkan banyak solusi.
aze45sq6d
30

jawaban hebat dari DuckPuncher, untuk Python3 pastikan Anda menginstal pdfminer2 dan lakukan:

import io

from pdfminer.pdfinterp import PDFResourceManager, PDFPageInterpreter
from pdfminer.converter import TextConverter
from pdfminer.layout import LAParams
from pdfminer.pdfpage import PDFPage


def convert_pdf_to_txt(path):
    rsrcmgr = PDFResourceManager()
    retstr = io.StringIO()
    codec = 'utf-8'
    laparams = LAParams()
    device = TextConverter(rsrcmgr, retstr, codec=codec, laparams=laparams)
    fp = open(path, 'rb')
    interpreter = PDFPageInterpreter(rsrcmgr, device)
    password = ""
    maxpages = 0
    caching = True
    pagenos = set()

    for page in PDFPage.get_pages(fp, pagenos, maxpages=maxpages,
                                  password=password,
                                  caching=caching,
                                  check_extractable=True):
        interpreter.process_page(page)



    fp.close()
    device.close()
    text = retstr.getvalue()
    retstr.close()
    return text
juan Isaza
sumber
1
Itu tidak berfungsi untuk saya: ModuleNotFoundError: Tidak ada modul bernama 'pdfminer.pdfpage' saya menggunakan python 3.6
Atti
@Atti, untuk berjaga-jaga, pastikan Anda telah menginstal pdfminer2, karena ada paket lain pdfminer (saya benci ini). Ini berfungsi untuk pdfminer2 == versi 20151206 saat melakukan pembekuan pip3.
juan Isaza
5
terima kasih akhirnya saya berhasil, saya menginstal pdfminer.six dari conda forge
Atti
8
Untuk Python 3, pdfminer.six adalah paket yang direkomendasikan - github.com/pdfminer/pdfminer.six
Mike Driscoll
Apakah ini masih terkini. Saya mendapatkan ImportError:pesan yang sama
14

Ini berfungsi pada Mei 2020 menggunakan PDFminer enam dengan Python3.

Menginstal paket

$ pip install pdfminer.six

Mengimpor paket

from pdfminer.high_level import extract_text

Menggunakan PDF yang disimpan di disk

text = extract_text('report.pdf')

Atau sebagai alternatif:

with open('report.pdf','rb') as f:
    text = extract_text(f)

Menggunakan PDF yang sudah ada di memori

Jika PDF sudah ada di memori, misalnya jika diambil dari web dengan pustaka permintaan, itu bisa diubah menjadi aliran menggunakan iopustaka:

import io

response = requests.get(url)
text = extract_text(io.BytesIO(response.content))

Kinerja dan Keandalan dibandingkan dengan PyPDF2

PDFminer.six bekerja lebih andal daripada PyPDF2 (yang gagal dengan jenis PDF tertentu), khususnya PDF versi 1.7

Namun, ekstraksi teks dengan PDFminer.six secara signifikan lebih lambat daripada PyPDF2 dengan faktor 6.

Saya menghitung waktu ekstraksi teks dengan timeit15 "MBP (2018), hanya mengatur waktu fungsi ekstraksi (tidak ada pembukaan file, dll.) Dengan PDF 10 halaman dan mendapatkan hasil sebagai berikut:

PDFminer.six: 2.88 sec
PyPDF2:       0.45 sec

pdfminer.six juga memiliki footprint yang sangat besar, membutuhkan pycryptodome yang membutuhkan GCC dan hal-hal lain yang diinstal mendorong gambar instal docker minimal di Alpine Linux dari 80 MB menjadi 350 MB. PyPDF2 tidak memiliki dampak penyimpanan yang nyata.

Cornelius Roemer
sumber
Pendekatan ini mungkin telah rusak sejak pembaruan terakhir. Saat ini mendapatkan kesalahan ImportError: cannot import name 'open_filename' from 'pdfminer.utils'ketika saya menjalankanfrom pdfminer.high_level import extract_text
Bacaan Lebih Lanjut
1
Pembaruan: Saya memperbaikinya dengan membuat venv baru dan menginstal ulang pdfminer.six. Saya kira salah satu paket pdf lain yang saya coba sebelumnya entah bagaimana mengganggu.
Bacaan Lebih Lanjut
11

Pengungkapan penuh, saya salah satu pengelola pdfminer.six.

Saat ini, ada beberapa api untuk mengekstrak teks dari PDF, tergantung kebutuhan Anda. Di balik layar, semua api ini menggunakan logika yang sama untuk mengurai dan menganalisis tata letak.

(Semua contoh menganggap file PDF Anda disebut example.pdf )

Garis komando

Jika Anda ingin mengekstrak teks sekali saja, Anda dapat menggunakan alat baris perintah pdf2txt.py:

$ pdf2txt.py example.pdf

Api tingkat tinggi

Jika Anda ingin mengekstrak teks dengan Python, Anda dapat menggunakan api tingkat tinggi. Pendekatan ini adalah solusi masuk jika Anda ingin mengekstrak teks secara terprogram dari banyak PDF.

from pdfminer.high_level import extract_text

text = extract_text('example.pdf')

Api yang dapat disusun

Ada juga api yang dapat disusun yang memberikan banyak fleksibilitas dalam menangani objek yang dihasilkan. Misalnya, Anda dapat menerapkan algoritme tata letak Anda sendiri menggunakan itu. Metode ini disarankan dalam jawaban lain, tetapi saya hanya akan merekomendasikan ini ketika Anda perlu menyesuaikan cara pdfminer.six berperilaku.

from io import StringIO

from pdfminer.converter import TextConverter
from pdfminer.layout import LAParams
from pdfminer.pdfdocument import PDFDocument
from pdfminer.pdfinterp import PDFResourceManager, PDFPageInterpreter
from pdfminer.pdfpage import PDFPage
from pdfminer.pdfparser import PDFParser

output_string = StringIO()
with open('example.pdf', 'rb') as in_file:
    parser = PDFParser(in_file)
    doc = PDFDocument(parser)
    rsrcmgr = PDFResourceManager()
    device = TextConverter(rsrcmgr, output_string, laparams=LAParams())
    interpreter = PDFPageInterpreter(rsrcmgr, device)
    for page in PDFPage.create_pages(doc):
        interpreter.process_page(page)

print(output_string.getvalue())
Pieter
sumber
0

kode ini diuji dengan pdfminer untuk python 3 (pdfminer-20191125)

from pdfminer.layout import LAParams
from pdfminer.converter import PDFPageAggregator
from pdfminer.pdfinterp import PDFResourceManager
from pdfminer.pdfinterp import PDFPageInterpreter
from pdfminer.pdfpage import PDFPage
from pdfminer.layout import LTTextBoxHorizontal

def parsedocument(document):
    # convert all horizontal text into a lines list (one entry per line)
    # document is a file stream
    lines = []
    rsrcmgr = PDFResourceManager()
    laparams = LAParams()
    device = PDFPageAggregator(rsrcmgr, laparams=laparams)
    interpreter = PDFPageInterpreter(rsrcmgr, device)
    for page in PDFPage.get_pages(document):
            interpreter.process_page(page)
            layout = device.get_result()
            for element in layout:
                if isinstance(element, LTTextBoxHorizontal):
                    lines.extend(element.get_text().splitlines())
    return lines
Brault Gilbert
sumber
Saya memiliki file PDF yang dapat saya konversi menggunakan alat Nitro Pro. Namun, ketika saya mencoba mengonversi PDF yang sama menggunakan kode yang diposting di sini, saya mendapatkan keluaran yang menunjukkan bahwa ada kesalahan izin. Ini hasilnya: ('dari Koleksi Ilmu Sosial SAGE. Semua Hak Dilindungi Undang-Undang. \ N \ n \ x0c \ x0c \ x0c \ x0c \ x0c \ x0c \ x0c \ x0c \ x0c \ x0c \ x0c \ x0c \ x0c \ x0c \ x0c \ x0c \ x0c \ x0c \ x0c \ x0c \ x0c \ x0c \ x0c \ x0c \ x0c \ x0c \ x0c \ x0c \ x0c ')
b00kgrrl
Apa yang Anda maksud dengan aliran file?
Vincent
@ Vincent dengan buka (file, 'rb') sebagai aliran: [...]
Rodrigo Formighieri
apakah Anda berhasil mendapatkan file ini sebagai tabel / panda idealnya? groupe-psa.com/en/publication/monthly-world-sales-march-2020
Nono London