Cum se extrage textul dintr-un fișier PDF? (Programare, Python, Pdf)

Simplicitate a intrebat.

Încerc să extrag textul inclus în acest fișier PDF utilizând Python.

Folosesc extensia PyPDF2 și am următorul script:

import PyPDF2
pdf_file = open('sample.pdf')
read_pdf = PyPDF2.PdfFileReader(pdf_file)
number_of_pages = read_pdf.getNumPages()
page = read_pdf.getPage(0)
page_content = page.extractText()
print page_content

Când execut codul, obțin următorul rezultat, care este diferit de cel inclus în documentul PDF:

!"#$%#$%&%$&'()*%+,-%./01'*23%4
5'%1$#26%3/%7/))/8%&)/26%8#3"%3"*%313/9#&)
%

Cum pot extrage textul așa cum este în documentul PDF?

Comentarii

  • Nu am folosit niciodată acest modul, dar are vreo importanță dacă deschideți fișierul în modul binar: pdf_file = open('sample.pdf', 'rb')? –  > Por PM 2Ring.
  • Vă mulțumim pentru răspuns. Am încercat asta cu modul binar, dar nu s-a schimbat nimic –  > Por Simplicity.
  • Copiați textul folosind un vizualizator PDF bun – dacă este posibil, canonic Acrobat Reader de la Adobe. Obțineți același rezultat? Diferența nu constă în faptul că text este diferit, ci faptul că fontul este diferită – codurile caracterelor se asociază cu alte valori. Nu toate PDF-urile conțin datele corecte pentru a restabili acest lucru. –  > Por Jongware.
  • Acel PDF conține un tabel CMap de caractere, astfel încât restricțiile și soluțiile de rezolvare discutate în acest topic sunt relevante – stackoverflow.com/questions/4203414/…. –  > Por dwarring.
  • PDF-ul conține într-adevăr un CMAP corect, astfel încât este trivială conversia cartografierii ad-hoc a caracterelor în text simplu. Cu toate acestea, este nevoie de o procesare suplimentară pentru a prelua codul corect comandă a textului. Renderizatorul Quartz PDF de la Mac OS X este o piesă de lucru urâtă! În ordinea sa originală de redare, obțin „m T’h iuss iisn ga tosam fopllloew DalFo dnogc wumithe ntht eI tutorial”… Abia după sortarea după coordonatele x obțin un rezultat mult mai probabil corect: „Acesta este un exemplu de document PDF pe care îl folosesc pentru a urmări tutorialul”. –  > Por Jongware.
26 răspunsuri
DJK

Căutam o soluție simplă pe care să o folosesc pentru python 3.x și windows. Nu pare să existe suport din partea textract, , ceea ce este regretabil, dar dacă sunteți în căutarea unei soluții simple pentru windows/python 3 verificați tika care este foarte simplu pentru citirea pdf-urilor.

Tika-Python este o legătură Python pentru serviciile Apache Tika™ REST, care permite apelarea nativă a Tika în comunitatea Python.

from tika import parser # pip install tika

raw = parser.from_file('sample.pdf')
print(raw['content'])

Rețineți că Tika este scris în Java, deci veți avea nevoie de un runtime Java instalat.

Comentarii

    20

  • Am testat pypdf2, tika și am încercat și nu am reușit să instalez textract și pdftotext. Pypdf2 a returnat 99 de cuvinte, în timp ce tika a returnat toate cele 858 de cuvinte din factura mea de test. Așa că am sfârșit prin a alege tika. –  > Por Stian.
  • 20

  • Continui să primesc un mesaj „RuntimeError: Unable to start Tika server”. –  > Por Nav.
  • Răspunsul pe care l-am căutat toată viața mea, de ce nimeni nu recomandă Tika? Mulțumesc! –  > Por Jacob-Jan Mosselman.
  • Dacă aveți nevoie să executați acest lucru pe toate fișierele PDF dintr-un director (recursiv), luați acest script –  > Por Hope.
  • pentru cine are eroarea „Unable to start Tika server”, am rezolvat instalarea ultimei versiuni de Java, așa cum este sugerat aici, pe care am făcut-o pe Mac Os X cu brew urmând acest răspuns –  > Por glS.
Jakobovski

Utilizați textract.

Acceptă multe tipuri de fișiere, inclusiv PDF-uri

import textract
text = textract.process("path/to/file.extension")

Comentarii

    25

  • Textwrap pare a fi un înveliș frumos, dar se bazează pe numeroase utilități non-Python care ar putea să nu fie disponibile cu ușurință pe un anumit sistem. –  > Por David Brown.
  • Funcționează pentru PDF-uri, epub-uri etc. – procesează PDF-uri la care nici măcar PDFMiner nu reușește. –  > Por Ulad Kasach.
  • textract este un wrapper pentru Poppler:pdftotext (printre altele). –  > Por onewhaleid.
  • @ArunKumar: Pentru a utiliza ceva în AWS Lambda care nu este încorporat, trebuie să îl includeți și toate dependențele suplimentare, în pachetul dvs. –  > Por Jeff Learman.
  • textract pare să fie mort (sursa). Utilizați fie pdfminer.six direct, fie pymupdf –  > Por Martin Thoma.
Quinn

Uitați-vă la acest cod:

import PyPDF2
pdf_file = open('sample.pdf', 'rb')
read_pdf = PyPDF2.PdfFileReader(pdf_file)
number_of_pages = read_pdf.getNumPages()
page = read_pdf.getPage(0)
page_content = page.extractText()
print page_content.encode('utf-8')

Ieșirea este:

!"#$%#$%&%$&'()*%+,-%./01'*23%4
5'%1$#26%3/%7/))/8%&)/26%8#3"%3"*%313/9#&)
%

Folosind același cod pentru a citi un pdf din 201308FCR.pdf.ieșirea este normală.

Este documentația explică de ce:

def extractText(self):
    """
    Locate all text drawing commands, in the order they are provided in the
    content stream, and extract the text.  This works well for some PDF
    files, but poorly for others, depending on the generator used.  This will
    be refined in the future.  Do not rely on the order of text coming out of
    this function, as it will change if this function is made more
    sophisticated.
    :return: a unicode string object.
    """

Comentarii

  • @VineeshTP: Primești ceva pentru page_content? Dacă da, atunci vedeți dacă vă ajută folosind o altă codificare decât (utf-8) –  > Por Quinn.
  • Cea mai bună bibliotecă pe care am găsit-o pentru citirea pdf-ului folosind python este „tika” –  > Por Vineesh TP.
  • 201308FCR.pdf nu a fost găsit. –  > Por Chaitanya Bapat.
  • PyPDF2 / PyPDF3 / PyPDF4 sunt toate moarte. Utilizați pymupdf –  > Por Martin Thoma.
hansaplast

După ce am încercat textract (care părea să aibă prea multe dependențe) și pypdf2 (care nu a putut extrage text din pdf-urile cu care am testat) și tika (care a fost prea lent) am ajuns să folosesc pdftotext de la xpdf (așa cum a fost deja sugerat într-un alt răspuns) și am apelat pur și simplu binarul direct din python (poate că va trebui să adaptați calea către pdftotext):

import os, subprocess
SCRIPT_DIR = os.path.dirname(os.path.abspath(__file__))
args = ["/usr/local/bin/pdftotext",
        '-enc',
        'UTF-8',
        "{}/my-pdf.pdf".format(SCRIPT_DIR),
        '-']
res = subprocess.run(args, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
output = res.stdout.decode('utf-8')

Există pdftotext care face practic același lucru, dar acesta presupune că pdftotext se află în /usr/local/bin, în timp ce eu îl folosesc în AWS lambda și am vrut să îl folosesc din directorul curent.

Btw: Pentru a folosi acest lucru în lambda trebuie să puneți binarul și dependența în libstdc++.so în funcția lambda. Personal, am avut nevoie să compilez xpdf. Deoarece instrucțiunile pentru acest lucru ar arunca în aer acest răspuns, le-am pus pe blogul meu personal.

Comentarii

  • Oh, Doamne, funcționează!!! În sfârșit, o soluție care extrage textul în ordinea corectă! Vreau să te îmbrățișez pentru acest răspuns! (Sau dacă nu vă plac îmbrățișările, iată o cafea/bere virtuală/…) – -.  > Por DonQuiKong.
  • Mă bucur că a ajutat! Upvoting-ul dă aceeași senzație ca și îmbrățișarea, așa că sunt bine! –  > Por hansaplast.
  • simplu … gr8 out of box thinking! –  > Por shantanu pathak.
Martin Thoma

Vă recomand să utilizați pymupdf sau pdfminer.six.

Aceste pachete nu sunt întreținute:

  • PyPDF2, PyPDF3, PyPDF4
  • pdfminer (fără .six)

Cum să citiți text pur cu pymupdf

Există diferite opțiuni care vor da rezultate diferite, dar cea mai de bază este:

import fitz  # this is pymupdf

with fitz.open("my.pdf") as doc:
    text = ""
    for page in doc:
        text += page.getText()

print(text)

Comentarii

  • Cu siguranță cel mai simplu mod de a citi un PDF, mulțumesc! –  > Por martin36.
  • Cu toate acestea, se pare că există o problemă cu ordinea textului din PDF. În mod intuitiv, textul ar trebui să se citească de sus în jos și de la stânga la dreapta, dar aici pare să apară în altă ordine –  > Por martin36.
erfelipe

Am încercat multe convertoare PDF Python și îmi place să actualizez această recenzie. Tika este unul dintre cele mai bune. Dar PyMuPDF este o veste bună de la utilizatorul @ehsaneha.

Am făcut un cod pentru a le compara în: https://github.com/erfelipe/PDFtextExtraction Sper să vă ajut.

Tika-Python este o legătură Python pentru serviciile Apache Tika™ REST, permițând ca Tika să fie apelat nativ în comunitatea Python.

from tika import parser

raw = parser.from_file("///Users/Documents/Textos/Texto1.pdf")
raw = str(raw)

safe_text = raw.encode('utf-8', errors='ignore')

safe_text = str(safe_text).replace("
", "").replace("\", "")
print('--- safe text ---' )
print( safe_text )

Comentarii

  • mulțumiri speciale pentru .encode('utf-8', errors='ignore') –  > Por Evgeny.
  • AttributeError: modulul ‘os’ nu are atributul ‘setsid’ –  > Por keramat.
Eugene

Este posibil să doriți să utilizați timpul dovedit xPDF și instrumentele derivate pentru a extrage textul în schimb, deoarece pyPDF2 pare să aibă diverse probleme cu extragerea textului.

Răspunsul lung este că există o mulțime de variații în modul în care un text este codificat în PDF și că ar putea fi necesară decodificarea șirului PDF în sine, apoi ar putea fi nevoie de maparea cu CMAP, apoi ar putea fi necesară analiza distanței dintre cuvinte și litere etc.

În cazul în care PDF-ul este deteriorat (adică afișează textul corect, dar la copiere dă un gunoi) și chiar aveți nevoie să extrageți textul, atunci poate doriți să luați în considerare conversia PDF în imagine (utilizând ImageMagik) și apoi să utilizați Tesseract pentru a extrage textul din imagine folosind OCR.

Comentarii

  • -1 pentru că OP cere citirea PDF-urilor în Python și, deși există un wrapper xpdf pentru python, acesta este slab întreținut. –  > Por cduguet.
Steffi Keran Rani J

Codul de mai jos este o soluție la întrebarea din Python 3. Înainte de a rula codul, asigurați-vă că ați instalat programul PyPDF2 biblioteca în mediul dumneavoastră. Dacă nu este instalată, deschideți promptul de comandă și rulați următoarea comandă:

pip3 install PyPDF2

Soluție Cod:

import PyPDF2
pdfFileObject = open('sample.pdf', 'rb')
pdfReader = PyPDF2.PdfFileReader(pdfFileObject)
count = pdfReader.numPages
for i in range(count):
    page = pdfReader.getPage(i)
    print(page.extractText())

Comentarii

  • Cum ați putea salva tot conținutul într-un singur fișier text și să-l utilizați pentru analize ulterioare?  > Por Rahul Agarwal.
  • PyPDF2 / PyPDF3 / PyPDF4 sunt toate moarte. Utilizați pymupdf –  > Por Martin Thoma.
ehsaneha

PyPDF2 în unele cazuri ignoră spațiile albe și face ca textul rezultat să fie o mizerie, dar eu folosesc PyMuPDF și sunt foarte mulțumitputeți folosi acest lucru link pentru mai multe informații

Comentarii

  • pymupdf este cea mai bună soluție pe care am observat-o, nu necesită biblioteci C++ suplimentare ca pdftotext sau java ca tika –  > Por Kay.
  • pymypdf este într-adevăr cea mai bună soluție, nu are server sau biblioteci suplimentare și funcționează cu fișiere în care PyPDF2 PypDF3 PyPDF4 retrive șirul gol de text. multe mulțumiri! –  > Por Andrea Bisello.
  • pentru a instala pymupdf, rulați pip install pymupdf==1.16.16. Folosind această versiune specifică, deoarece astăzi cea mai nouă versiune (17) nu funcționează. Am optat pentru pymupdf pentru că extrage câmpurile de înfășurare a textului în noua linie char
    . Așadar, extrag textul din pdf într-un șir de caractere cu pymupdf și apoi folosesc my_extracted_text.splitlines() pentru a obține textul împărțit în linii, într-o listă. –  > Por erickfis.
  • PyMuPDF a fost cu adevărat surprinzător. Mulțumesc. –  > Por erfelipe.
  • Pagina nu există –  > Por Black Thunder.
Dharam

pdftotext este cel mai bun și cel mai simplu!pdftotext rezervă și structura de asemenea.

Am încercat PyPDF2, PDFMiner și alte câteva, dar niciunul nu a dat un rezultat satisfăcător.

Comentarii

  • Mesaj după cum urmează la instalarea pdf2text,Collecting PDFMiner (from pdf2text), , deci nu înțeleg acest răspuns acum. –  > Por zhy.
  • pdf2text și pdftotext sunt diferite. Puteți folosi link-ul din răspuns. –  > Por Dharam.
  • OK. Este puțin confuz. –  > Por zhy.
Yogi

Multi – pagina pdf poate fi extras ca text la o singură întindere în loc de a da numărul de pagină individuală ca argument folosind codul de mai jos

import PyPDF2
import collections
pdf_file = open('samples.pdf', 'rb')
read_pdf = PyPDF2.PdfFileReader(pdf_file)
number_of_pages = read_pdf.getNumPages()
c = collections.Counter(range(number_of_pages))
for i in c:
   page = read_pdf.getPage(i)
   page_content = page.extractText()
   print page_content.encode('utf-8')

Comentarii

  • Singura problemă aici este că conținutul noii pagini o suprascrie pe cea anterioară.  > Por Rahul Agarwal.
  • PyPDF2 / PyPDF3 / PyPDF4 sunt toate moarte. Utilizați pymupdf –  > Por Martin Thoma.
Jortega

În 2020, soluțiile de mai sus nu au funcționat pentru pdf-ul special cu care lucram. Mai jos este ceea ce a făcut truc. Sunt pe Windows 10 și Python 3.8

Fișier pdf de test: https://drive.google.com/file/d/1aUfQAlvq5hA9kz2c9CyJADiY3KpY3-Vn/view?usp=sharing

#pip install pdfminer.six
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):
    '''Convert pdf content from a file path to text

    :path the file path
    '''
    rsrcmgr = PDFResourceManager()
    codec = 'utf-8'
    laparams = LAParams()

    with io.StringIO() as retstr:
        with TextConverter(rsrcmgr, retstr, codec=codec,
                           laparams=laparams) as device:
            with open(path, 'rb') as fp:
                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)

                return retstr.getvalue()


if __name__ == "__main__":
    print(convert_pdf_to_txt('C:\Path\To\Test_PDF.pdf')) 

Comentarii

  • Un răspuns excelent. Există și o instalare anaconda. Am fost instalat și am extras textul în < 5 minute. [notă: a funcționat și tika, dar pdfminer.six a fost mult mai rapid) -.  > Por CreekGeek.
  • Sunteți un salvator de vieți! –  > Por Sandeep.
Máxima Alekz

Puteți utiliza PDFtoTexthttps://github.com/jalan/pdftotext

PDF to text păstrează indentarea în format text, nu contează dacă aveți tabele.

Strayhorn

Am o soluție mai bună decât OCR-ul și pentru a menține alinierea paginilor în timp ce extragi textul dintr-un PDF. Ar trebui să vă fie de ajutor:

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

text= convert_pdf_to_txt('test.pdf')
print(text)

Comentarii

  • Nb. Cea mai recentă versiune nu mai folosește codec arg . Am rezolvat acest lucru eliminându-l, adică. device = TextConverter(rsrcmgr, retstr, laparams=laparams) –  > Por atomh33ls.
Infinit

Iată cel mai simplu cod pentru extragerea textului

cod:

# importing required modules
import PyPDF2

# creating a pdf file object
pdfFileObj = open('filename.pdf', 'rb')

# creating a pdf reader object
pdfReader = PyPDF2.PdfFileReader(pdfFileObj)

# printing number of pages in pdf file
print(pdfReader.numPages)

# creating a page object
pageObj = pdfReader.getPage(5)

# extracting text from page
print(pageObj.extractText())

# closing the pdf file object
pdfFileObj.close()

Comentarii

  • Recomandați „tika” –  > Por Vineesh TP.
  • PyPDF2 / PyPDF3 / PyPDF4 sunt toate moarte. Utilizați pymupdf –  > Por Martin Thoma.
CreekGeek

Dacă doriți să extrageți text dintr-un tabel, am constatat că tabula este ușor de implementat, precis și rapid:

pentru a obține un cadru de date pandas:

import tabula

df = tabula.read_pdf('your.pdf')

df

În mod implicit, ignoră conținutul paginii din afara tabelului. Până acum, am testat doar pe un fișier cu o singură pagină și un singur tabel, dar există kwargs pentru a se adapta la mai multe pagini și/sau mai multe tabele.

Se instalează prin:

pip install tabula-py
# or
conda install -c conda-forge tabula-py 

În ceea ce privește extragerea directă a textului, consultați:https://stackoverflow.com/a/63190886/9249533

Comentarii

  • tabula este impresionant. Dintre toate soluțiile pe care le-am testat de pe această pagină, aceasta este singura care a reușit să mențină ordinea rândurilor și a câmpurilor. Mai sunt încă câteva ajustări necesare pentru tabelele complexe, dar, din moment ce rezultatul pare reproductibil de la un tabel la altul și este stocat într-un fișier pandas.DataFrame este ușor de corectat. –  > Por Skippy le Grand Gourou.
  • Verificați și Camelot. –  > Por Skippy le Grand Gourou.
Tho

Am găsit o soluție aici PDFLayoutTextStripper

Este bun pentru că poate păstra aspectul PDF-ului original.

Este scrisă în Java, dar am adăugat o poartă de acces pentru a suporta Python.

Exemplu de cod:

from py4j.java_gateway import JavaGateway

gw = JavaGateway()
result = gw.entry_point.strip('samples/bus.pdf')

# result is a dict of {
#   'success': 'true' or 'false',
#   'payload': pdf file content if 'success' is 'true'
#   'error': error message if 'success' is 'false'
# }

print result['payload']

Exemplu de ieșire din PDFLayoutTextStripper:

Puteți vedea mai multe detalii aici Stripper cu Python

Elavarasan r

Pentru extragerea textului din PDF folosiți codul de mai jos

import PyPDF2
pdfFileObj = open('mypdf.pdf', 'rb')

pdfReader = PyPDF2.PdfFileReader(pdfFileObj)

print(pdfReader.numPages)

pageObj = pdfReader.getPage(0)

a = pageObj.extractText()

print(a)

Comentarii

  • PyPDF2 / PyPDF3 / PyPDF4 sunt toate moarte. Utilizați pymupdf –  > Por Martin Thoma.
Andres Ordorica

O modalitate mai robustă, presupunând că există mai multe PDF-uri sau doar unul singur !

import os
from PyPDF2 import PdfFileWriter, PdfFileReader
from io import BytesIO

mydir = # specify path to your directory where PDF or PDF's are

for arch in os.listdir(mydir): 
    buffer = io.BytesIO()
    archpath = os.path.join(mydir, arch)
    with open(archpath) as f:
            pdfFileObj = open(archpath, 'rb')
            pdfReader = PyPDF2.PdfFileReader(pdfFileObj)
            pdfReader.numPages
            pageObj = pdfReader.getPage(0) 
            ley = pageObj.extractText()
            file1 = open("myfile.txt","w")
            file1.writelines(ley)
            file1.close()
            

Ritesh Shanker

Adaug codul pentru a realiza acest lucru: Funcționează bine pentru mine:

# This works in python 3
# required python packages
# tabula-py==1.0.0
# PyPDF2==1.26.0
# Pillow==4.0.0
# pdfminer.six==20170720

import os
import shutil
import warnings
from io import StringIO

import requests
import tabula
from PIL import Image
from PyPDF2 import PdfFileWriter, PdfFileReader
from pdfminer.converter import TextConverter
from pdfminer.layout import LAParams
from pdfminer.pdfinterp import PDFResourceManager, PDFPageInterpreter
from pdfminer.pdfpage import PDFPage

warnings.filterwarnings("ignore")


def download_file(url):
    local_filename = url.split('/')[-1]
    local_filename = local_filename.replace("%20", "_")
    r = requests.get(url, stream=True)
    print(r)
    with open(local_filename, 'wb') as f:
        shutil.copyfileobj(r.raw, f)

    return local_filename


class PDFExtractor():
    def __init__(self, url):
        self.url = url

    # Downloading File in local
    def break_pdf(self, filename, start_page=-1, end_page=-1):
        pdf_reader = PdfFileReader(open(filename, "rb"))
        # Reading each pdf one by one
        total_pages = pdf_reader.numPages
        if start_page == -1:
            start_page = 0
        elif start_page < 1 or start_page > total_pages:
            return "Start Page Selection Is Wrong"
        else:
            start_page = start_page - 1

        if end_page == -1:
            end_page = total_pages
        elif end_page < 1 or end_page > total_pages - 1:
            return "End Page Selection Is Wrong"
        else:
            end_page = end_page

        for i in range(start_page, end_page):
            output = PdfFileWriter()
            output.addPage(pdf_reader.getPage(i))
            with open(str(i + 1) + "_" + filename, "wb") as outputStream:
                output.write(outputStream)

    def extract_text_algo_1(self, file):
        pdf_reader = PdfFileReader(open(file, 'rb'))
        # creating a page object
        pageObj = pdf_reader.getPage(0)

        # extracting extract_text from page
        text = pageObj.extractText()
        text = text.replace("
", "").replace("t", "")
        return text

    def extract_text_algo_2(self, file):
        pdfResourceManager = PDFResourceManager()
        retstr = StringIO()
        la_params = LAParams()
        device = TextConverter(pdfResourceManager, retstr, codec='utf-8', laparams=la_params)
        fp = open(file, 'rb')
        interpreter = PDFPageInterpreter(pdfResourceManager, device)
        password = ""
        max_pages = 0
        caching = True
        page_num = set()

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

        text = retstr.getvalue()
        text = text.replace("t", "").replace("
", "")

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

    def extract_text(self, file):
        text1 = self.extract_text_algo_1(file)
        text2 = self.extract_text_algo_2(file)

        if len(text2) > len(str(text1)):
            return text2
        else:
            return text1

    def extarct_table(self, file):

        # Read pdf into DataFrame
        try:
            df = tabula.read_pdf(file, output_format="csv")
        except:
            print("Error Reading Table")
            return

        print("
Printing Table Content: 
", df)
        print("
Done Printing Table Content
")

    def tiff_header_for_CCITT(self, width, height, img_size, CCITT_group=4):
        tiff_header_struct = '<' + '2s' + 'h' + 'l' + 'h' + 'hhll' * 8 + 'h'
        return struct.pack(tiff_header_struct,
                           b'II',  # Byte order indication: Little indian
                           42,  # Version number (always 42)
                           8,  # Offset to first IFD
                           8,  # Number of tags in IFD
                           256, 4, 1, width,  # ImageWidth, LONG, 1, width
                           257, 4, 1, height,  # ImageLength, LONG, 1, lenght
                           258, 3, 1, 1,  # BitsPerSample, SHORT, 1, 1
                           259, 3, 1, CCITT_group,  # Compression, SHORT, 1, 4 = CCITT Group 4 fax encoding
                           262, 3, 1, 0,  # Threshholding, SHORT, 1, 0 = WhiteIsZero
                           273, 4, 1, struct.calcsize(tiff_header_struct),  # StripOffsets, LONG, 1, len of header
                           278, 4, 1, height,  # RowsPerStrip, LONG, 1, lenght
                           279, 4, 1, img_size,  # StripByteCounts, LONG, 1, size of extract_image
                           0  # last IFD
                           )

    def extract_image(self, filename):
        number = 1
        pdf_reader = PdfFileReader(open(filename, 'rb'))

        for i in range(0, pdf_reader.numPages):

            page = pdf_reader.getPage(i)

            try:
                xObject = page['/Resources']['/XObject'].getObject()
            except:
                print("No XObject Found")
                return

            for obj in xObject:

                try:

                    if xObject[obj]['/Subtype'] == '/Image':
                        size = (xObject[obj]['/Width'], xObject[obj]['/Height'])
                        data = xObject[obj]._data
                        if xObject[obj]['/ColorSpace'] == '/DeviceRGB':
                            mode = "RGB"
                        else:
                            mode = "P"

                        image_name = filename.split(".")[0] + str(number)

                        print(xObject[obj]['/Filter'])

                        if xObject[obj]['/Filter'] == '/FlateDecode':
                            data = xObject[obj].getData()
                            img = Image.frombytes(mode, size, data)
                            img.save(image_name + "_Flate.png")
                            # save_to_s3(imagename + "_Flate.png")
                            print("Image_Saved")

                            number += 1
                        elif xObject[obj]['/Filter'] == '/DCTDecode':
                            img = open(image_name + "_DCT.jpg", "wb")
                            img.write(data)
                            # save_to_s3(imagename + "_DCT.jpg")
                            img.close()
                            number += 1
                        elif xObject[obj]['/Filter'] == '/JPXDecode':
                            img = open(image_name + "_JPX.jp2", "wb")
                            img.write(data)
                            # save_to_s3(imagename + "_JPX.jp2")
                            img.close()
                            number += 1
                        elif xObject[obj]['/Filter'] == '/CCITTFaxDecode':
                            if xObject[obj]['/DecodeParms']['/K'] == -1:
                                CCITT_group = 4
                            else:
                                CCITT_group = 3
                            width = xObject[obj]['/Width']
                            height = xObject[obj]['/Height']
                            data = xObject[obj]._data  # sorry, getData() does not work for CCITTFaxDecode
                            img_size = len(data)
                            tiff_header = self.tiff_header_for_CCITT(width, height, img_size, CCITT_group)
                            img_name = image_name + '_CCITT.tiff'
                            with open(img_name, 'wb') as img_file:
                                img_file.write(tiff_header + data)

                            # save_to_s3(img_name)
                            number += 1
                except:
                    continue

        return number

    def read_pages(self, start_page=-1, end_page=-1):

        # Downloading file locally
        downloaded_file = download_file(self.url)
        print(downloaded_file)

        # breaking PDF into number of pages in diff pdf files
        self.break_pdf(downloaded_file, start_page, end_page)

        # creating a pdf reader object
        pdf_reader = PdfFileReader(open(downloaded_file, 'rb'))

        # Reading each pdf one by one
        total_pages = pdf_reader.numPages

        if start_page == -1:
            start_page = 0
        elif start_page < 1 or start_page > total_pages:
            return "Start Page Selection Is Wrong"
        else:
            start_page = start_page - 1

        if end_page == -1:
            end_page = total_pages
        elif end_page < 1 or end_page > total_pages - 1:
            return "End Page Selection Is Wrong"
        else:
            end_page = end_page

        for i in range(start_page, end_page):
            # creating a page based filename
            file = str(i + 1) + "_" + downloaded_file

            print("
Starting to Read Page: ", i + 1, "
 -----------===-------------")

            file_text = self.extract_text(file)
            print(file_text)
            self.extract_image(file)

            self.extarct_table(file)
            os.remove(file)
            print("Stopped Reading Page: ", i + 1, "
 -----------===-------------")

        os.remove(downloaded_file)


# I have tested on these 3 pdf files
# url = "http://s3.amazonaws.com/NLP_Project/Original_Documents/Healthcare-January-2017.pdf"
url = "http://s3.amazonaws.com/NLP_Project/Original_Documents/Sample_Test.pdf"
# url = "http://s3.amazonaws.com/NLP_Project/Original_Documents/Sazerac_FS_2017_06_30%20Annual.pdf"
# creating the instance of class
pdf_extractor = PDFExtractor(url)

# Getting desired data out
pdf_extractor.read_pages(15, 23)

pah8J

Puteți descărca tika-app-xxx.jar (cel mai recent) de la Aici.

Apoi, puneți acest fișier .jar în același dosar cu fișierul de script python.

apoi inserați următorul cod în script:

import os
import os.path

tika_dir=os.path.join(os.path.dirname(__file__),'<tika-app-xxx>.jar')

def extract_pdf(source_pdf:str,target_txt:str):
    os.system('java -jar '+tika_dir+' -t {} > {}'.format(source_pdf,target_txt))

Avantajul acestei metode:

mai puține dependențe. Un singur fișier .jar este mai ușor de gestionat decât un pachet python.

suport multiformat. Poziția source_pdf poate fi directorul oricărui tip de document. (.doc, .html, .odt, etc.)

actualizat. tika-app.jar se lansează întotdeauna mai devreme decât versiunea relevantă a pachetului python tika.

stabilă. Este mult mai stabil și bine întreținut (Powered by Apache) decât PyPDF.

dezavantaj:

Este necesar un jre-headless.

Comentarii

  • soluție total nepythonică. Dacă recomandați acest lucru, ar trebui să construiți un pachet python și să cereți oamenilor să îl importe. Nu recomandați utilizarea execuțiilor în linie de comandă a codului java în python. –  > Por Michael Tamillow.
  • @MichaelTamillow, dacă scrieți un cod care va fi încărcat în pypi, recunosc că nu este o idee bună. Cu toate acestea, dacă este doar un script python cu shebang pentru utilizare temporară, nu este rău, nu-i așa? –  > Por pah8J.
  • Ei bine, întrebarea nu este intitulată cu „python” – așa că cred că afirmarea „iată cum se face în Java” este mai acceptabilă decât aceasta. Din punct de vedere tehnic, puteți face orice doriți în Python. De aceea este atât minunat, cât și teribil. Utilizarea temporară este un obicei prost. –  > Por Michael Tamillow.
DovaX

Dacă încercați în Anaconda pe Windows, este posibil ca PyPDF2 să nu gestioneze unele dintre PDF-urile cu structură non-standard sau caractere unicode. Vă recomand să folosiți următorul cod dacă aveți nevoie să deschideți și să citiți multe fișiere pdf – textul tuturor fișierelor pdf din folderul cu cale relativă .//pdfs// va fi stocat în lista pdf_text_list.

from tika import parser
import glob

def read_pdf(filename):
    text = parser.from_file(filename)
    return(text)


all_files = glob.glob(".\pdfs\*.pdf")
pdf_text_list=[]
for i,file in enumerate(all_files):
    text=read_pdf(file)
    pdf_text_list.append(text['content'])

print(pdf_text_list)

alpha

Utilizați pdfminer.six. Aici este documentul: https://pdfminersix.readthedocs.io/en/latest/index.html

Pentru a converti pdf în text :

    def pdf_to_text():
        from pdfminer.high_level import extract_text

        text = extract_text('test.pdf')
        print(text)

Skippy le Grand Gourou

Camelot pare o soluție destul de puternică pentru a extrage tabele din PDF-uri în Python.

La prima vedere pare să realizeze o extracție aproape la fel de precisă ca și cea a tabula-py pachet sugerat de CreekGeek, care este deja waaaaay deasupra oricărei alte soluții postate până în prezent în ceea ce privește fiabilitatea, dar se presupune că este mult mai ușor de configurat. În plus, are propriul său indicator de precizie (results.parsing_report), și caracteristici de depanare excelente.

Atât Camelot, cât și Tabula oferă rezultatele sub forma unor DataFrame de la Pandas, astfel încât este ușor să se ajusteze tabelele ulterior.

pip install camelot-py

(A nu se confunda cu camelot pachet).

import camelot

df_list = []
results = camelot.read_pdf("file.pdf", ...)
for table in results:
    print(table.parsing_report)
    df_list.append(results[0].df)

De asemenea, poate ieși rezultatele în format CSV, JSON, HTML sau Excel.

Camelot vine în detrimentul unui număr de dependențe.

NB : Deoarece datele mele de intrare sunt destul de complexe, cu multe tabele diferite, am ajuns să folosesc atât Camelot și Tabula, în funcție de tabel, pentru a obține cele mai bune rezultate.

bmc

PyPDF2 funcționează, dar rezultatele pot varia. Constat rezultate destul de inconsecvente în urma extragerii rezultatelor sale.

reader=PyPDF2.pdf.PdfFileReader(self._path)
eachPageText=[]
for i in range(0,reader.getNumPages()):
    pageText=reader.getPage(i).extractText()
    print(pageText)
    eachPageText.append(pageText)

Comentarii

  • PyPDF2 / PyPDF3 / PyPDF4 sunt toate moarte. Utilizați pymupdf –  > Por Martin Thoma.
Basile Starynkevitch

Cum se extrage textul dintr-un fișier PDF?

Primul lucru pe care trebuie să-l înțelegem este formatul PDF. Acesta are o specificație publică scrisă în limba engleză, vezi ISO 32000-2:2017 și citiți cele peste 700 de pagini de Specificația PDF 1.7. Cu siguranță trebuie cel puțin să citiți pagina wikipedia despre PDF

Odată ce ați înțeles detaliile formatului PDF, extragerea textului este mai mult sau mai puțin ușoară (dar ce se întâmplă cu textul care apare în figuri sau imagini; figura 1)? Nu vă așteptați să scrieți singur un software perfect de extragere a textului în câteva săptămâni….

Pe Linux, ați putea utiliza, de asemenea, următoarele pdf2text pe care l-ați putea popen din codul dumneavoastră Python.

În general, extragerea de text dintr-un fișier PDF este o problemă prost definită. Pentru un cititor uman, o parte din text ar putea fi format (ca o figură) din diferite puncte, sau dintr-o fotografie etc…

Motorul de căutare Google este capabil să extragă text din PDF, dar se zvonește că are nevoie de peste o jumătate de miliard de linii de cod sursă. Aveți resursele necesare (în forță de muncă, în buget) pentru a dezvolta un concurent?

O posibilitate ar putea fi imprimarea PDF-ului pe o imprimantă virtuală oarecare (de exemplu, folosind GhostScript sau Firefox), apoi să utilizați OCR pentru a extrage textul.

V-aș recomanda, în schimb, să lucrați la reprezentarea datelor care a generat fișierul PDF respectiv, de exemplu la originalul LaTeX (sau Lout code) sau pe OOXML cod.

În toate cazurile, trebuie să bugetați cel puțin câțiva ani-personă de dezvoltare de software.

Comentarii

  • Acesta nu este un răspuns. Spune să citiți acest document de 700 de pagini și nu oferă o abordare pentru a răspunde efectiv la întrebare. –  > Por xcski.
  • @xcski: Mi-am îmbunătățit răspunsul. Nu ezitați să mă contactați prin e-mail la adresa [email protected] menționând adresa URL a acestei întrebări –  > Por Basile Starynkevitch.

Tags:,