Trích xuất văn bản từ tệp PDF bằng PDFMiner trong python?


87

Tôi đang tìm tài liệu hoặc ví dụ về cách trích xuất văn bản từ tệp PDF bằng PDFMiner với Python.

Có vẻ như PDFMiner đã cập nhật API của họ và tất cả các ví dụ liên quan mà tôi tìm thấy đều chứa mã lỗi thời (các lớp và phương thức đã thay đổi). Các thư viện tôi đã tìm thấy rằng làm cho tác vụ trích xuất văn bản từ tệp PDF dễ dàng hơn đang sử dụng cú pháp PDFMiner cũ, vì vậy tôi không chắc chắn về cách thực hiện việc này.

Hiện tại, tôi chỉ đang xem mã nguồn để xem liệu tôi có thể tìm ra nó hay không.


1
Vui lòng xem stackoverflow.com/help/how-to-askstackoverflow.com/help/mcve và cập nhật câu trả lời của bạn để câu trả lời có định dạng tốt hơn và phù hợp với nguyên tắc.
Parker

Bạn đang sử dụng bản phân phối Python nào, 2.7.x hay 3.xx? Cần lưu ý rằng tác giả đã nêu chi tiết rõ ràng rằng PDFminernó không hoạt động với Python 3.xx Đó có thể là lý do khiến bạn gặp importlỗi. Bạn nên sử dụng pdfminer3knếu vậy, vì nó là bản nhập Python 3 thường trực của thư viện đã nói.
NullDev

@Nanashi, xin lỗi, tôi đã quên thêm phiên bản Python của mình. Nó là 2,7 nên đó không phải là vấn đề. Tôi đã xem qua mã nguồn và có vẻ như họ đã cấu trúc lại một số thứ, đó là lý do tại sao quá trình nhập bị phá vỡ. Tôi không thể tìm thấy bất kỳ tài liệu cho PDFMiner một trong hai hoặc tôi sẽ chỉ được làm việc tắt của :( rằng
DuckPuncher

Tôi vừa mới cài đặt PDFminerxong GitHub và nó nhập tốt. Bạn có thể vui lòng đăng mã của mình và đăng cả lỗi đầy đủ của bạn không?
NullDev

@Nanashi, Giống như tôi đã nói trong câu hỏi ban đầu của mình, các thư viện dựa trên PDFMiner sẽ ngắt trước khi kết thúc quá trình nhập cùng với bất kỳ ví dụ nào mà tôi có thể tìm thấy. Đây không phải là vấn đề PDFMiner. Đây là tôi đang tìm tài liệu hoặc ví dụ về cách sử dụng PDFMiner. Mọi thứ tôi có thể tìm thấy đang sử dụng một cú pháp cũ cho PDFMiner. Tôi đã tiếp tục và chỉnh sửa câu hỏi của mình cho rõ ràng. Tôi nghĩ rằng tôi đã làm cho nó khó hiểu hơn mức cần thiết. Xin lỗi vì điều đó.
DuckPuncher

Câu trả lời:


182

Đây là một ví dụ hoạt động của việc trích xuất văn bản từ tệp PDF bằng phiên bản PDFMiner hiện tại (tháng 9 năm 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

Cấu trúc của PDFMiner đã thay đổi gần đây, vì vậy cấu trúc này sẽ hoạt động để trích xuất văn bản từ các tệp PDF.

Chỉnh sửa : Vẫn hoạt động kể từ ngày 7 tháng 6 năm 2018. Đã xác minh trong phiên bản Python 3.x

Chỉnh sửa: Giải pháp hoạt động với Python 3.7 vào ngày 3 tháng 10 năm 2019. Tôi đã sử dụng thư viện Python pdfminer.six, được phát hành vào tháng 11 năm 2018.


2
hoạt động tốt, nhưng, làm cách nào để xử lý các khoảng trắng trong tên ví dụ? giả sử tôi có một pdf có chứa 4 cột nơi tôi có thứ nhất và lastname trong một col, bây giờ nó được phân tách với firstname trong một hàng và lastname trong một hàng, sau đây là một ví dụ docdro.id/rRyef3x
Deusdeorum

2
Hiện đang gặp lỗi nhập với mã này: ImportError: Không có mô-đun nào có tên 'pdfminer.pdfpage'
Jeffrey Swan

1
Cảm ơn nó hoạt động trên python v2.7.12 và trên ubuntu 16.04, mặc dù sẽ tốt hơn nếu tải tài liệu pdf với mã hóa utf-8, vì pdf mẫu của tôi có một số vấn đề mã hóa, vì vậy hãy thử điều này sau khi mã hóa bằng utf-8 và nó giải quyết được vấn đề ... import sys reload(sys) sys.setdefaultencoding('utf-8')
sib10

2
@DuckPuncher, Hiện nó vẫn hoạt động chứ? Tôi đã phải thay đổi file(path, 'rb')thành `open (path, 'rb') để bắt đầu hoạt động.
craned

2
Vẫn hoạt động cho người dùng Python3.7. Đã cài đặt gói pdfminer.six == 20181108. Giải pháp tốt nhất cho đến nay cho trường hợp của tôi và tôi đã so sánh nhiều giải pháp.
aze45sq6d

29

câu trả lời tuyệt vời từ DuckPuncher, cho Python3, hãy đảm bảo rằng bạn cài đặt pdfminer2 và thực hiện:

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

1
Nó không làm việc cho tôi: ModuleNotFoundError: Không có mô-đun có tên là 'pdfminer.pdfpage' i đang sử dụng python 3.6
ATTI

@Atti, đề phòng trường hợp, hãy đảm bảo rằng bạn đã cài đặt pdfminer2, vì có một gói pdfminer khác (tôi ghét điều này). Nó hoạt động cho phiên bản pdfminer2 == 20151206 khi làm đóng băng pip3.
juan Isaza

5
nhờ tôi nhận nó làm việc cuối cùng, tôi cài đặt pdfminer.six từ conda rèn
ATTI

8
Đối với Python 3, pdfminer.six là gói đề nghị - github.com/pdfminer/pdfminer.six
Mike Driscoll

Điều này vẫn còn hiện tại. Tôi cũng nhận được ImportError:thông báo tương tự

12

Tính năng này hoạt động vào tháng 5 năm 2020 bằng cách sử dụng PDFminer sáu trong Python3.

Cài đặt gói

$ pip install pdfminer.six

Nhập gói hàng

from pdfminer.high_level import extract_text

Sử dụng tệp PDF được lưu trên đĩa

text = extract_text('report.pdf')

Hay cách khác:

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

Sử dụng PDF đã có trong bộ nhớ

Nếu tệp PDF đã có trong bộ nhớ, chẳng hạn như nếu được truy xuất từ ​​web với thư viện yêu cầu, nó có thể được chuyển đổi thành một luồng bằng iothư viện:

import io

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

Hiệu suất và độ tin cậy so với PyPDF2

PDFminer.six hoạt động đáng tin cậy hơn PyPDF2 (không thành công với một số loại PDF nhất định), cụ thể là phiên bản PDF 1.7

Tuy nhiên, trích xuất văn bản bằng PDFminer.six chậm hơn đáng kể so với PyPDF2 theo hệ số 6.

Tôi đã hẹn giờ trích xuất văn bản timeittrên MBP 15 "(2018), chỉ định thời gian cho chức năng trích xuất (không mở tệp, v.v.) với PDF 10 trang và nhận được kết quả sau:

PDFminer.six: 2.88 sec
PyPDF2:       0.45 sec

pdfminer.six cũng có một dấu ấn lớn, yêu cầu pycryptodome cần GCC và những thứ khác được cài đặt đẩy một hình ảnh docker cài đặt tối thiểu trên Alpine Linux từ 80 MB đến 350 MB. PyPDF2 không có tác động lưu trữ đáng chú ý.


Cách tiếp cận này có thể đã bị hỏng kể từ lần cập nhật cuối cùng. Hiện đang gặp lỗi ImportError: cannot import name 'open_filename' from 'pdfminer.utils'khi tôi chạyfrom pdfminer.high_level import extract_text
Đọc thêm

1
Cập nhật: Tôi đã sửa lỗi này bằng cách tạo một venv mới và cài đặt lại pdfminer.six. Tôi đoán một trong những gói pdf khác mà tôi đã thử trước đó đang gây nhiễu bằng cách nào đó.
Đọc thêm

9

Tiết lộ đầy đủ, tôi là một trong những người duy trì pdfminer.six.

Ngày nay, có nhiều api để trích xuất văn bản từ PDF, tùy thuộc vào nhu cầu của bạn. Đằng sau hậu trường, tất cả các api này sử dụng cùng một logic để phân tích cú pháp và phân tích bố cục.

Dòng lệnh

Nếu bạn muốn trích xuất văn bản chỉ một lần, bạn có thể sử dụng công cụ dòng lệnh pdf2txt.py:

$ pdf2txt.py example.pdf

Api cấp cao

Nếu bạn muốn trích xuất văn bản bằng Python, bạn có thể sử dụng api cấp cao. Cách tiếp cận này là giải pháp tối ưu nếu bạn muốn trích xuất văn bản theo chương trình từ nhiều tệp PDF.

from pdfminer.high_level import extract_text

text = extract_text('samples/simple1.pdf')

Api dùng một lần

Ngoài ra còn có một api có thể kết hợp mang lại sự linh hoạt trong việc xử lý các đối tượng kết quả. Ví dụ: bạn có thể triển khai thuật toán bố cục của riêng mình bằng cách sử dụng điều đó. Phương pháp này được đề xuất trong các câu trả lời khác, nhưng tôi chỉ đề xuất phương pháp này khi bạn cần tùy chỉnh cách pdfminer.six hoạt động.

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('samples/simple1.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())

0

mã này được thử nghiệm với pdfminer cho 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

Tôi có các tệp PDF mà tôi có thể chuyển đổi bằng công cụ Nitro Pro. Tuy nhiên, khi tôi cố gắng chuyển đổi cùng một tệp PDF bằng cách sử dụng mã được đăng ở đây, tôi nhận được kết quả cho thấy rằng có lỗi quyền. Đây là kết quả đầu ra: ('từ Bộ sưu tập Khoa học Xã hội SAGE. Mọi Quyền được Bảo lưu. \ 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

Ý bạn là gì về luồng tệp?
Vincent

@Vincent với mở (tệp, 'rb') dưới dạng luồng: [...]
Rodrigo Formighieri

bạn có quản lý để lấy tệp này dưới dạng bảng / gấu trúc một cách lý tưởng không? Goope-psa.com/en/publication/monthly-world-sales-march-2020
Nono London
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.