pdfminer - Text extrahieren

Wenn du dir nicht sicher bist, in welchem der anderen Foren du die Frage stellen sollst, dann bist du hier im Forum für allgemeine Fragen sicher richtig.
Antworten
Knollo
User
Beiträge: 28
Registriert: Mittwoch 10. Juni 2020, 14:44

Hallo, ich versuche grad Text von einer bestimmten Position aus einem pdf-Dokument zu extrahieren.

Code: Alles auswählen

# https://stackoverflow.com/questions/22898145/how-to-extract-text-and-text-coordinates-from-a-pdf-file

from pathlib import Path
from typing import Iterable, Any
from pdfminer.high_level import extract_pages


def show_ltitem_hierarchy(o: Any, depth=0):
    """Show location and text of LTItem and all its descendants"""
    if depth == 0:
        print('element                        x1  y1  x2  y2   text')
        print('------------------------------ --- --- --- ---- -----')

    print(
        f'{get_indented_name(o, depth):<30.30s} '
        f'{get_optional_bbox(o)} '
        f'{get_optional_text(o)}'
    )

    if isinstance(o, Iterable):
        for i in o:
            show_ltitem_hierarchy(i, depth=depth + 1)


def get_indented_name(o: Any, depth: int) -> str:
    """Indented name of LTItem"""
    return '  ' * depth + o.__class__.__name__


def get_optional_bbox(o: Any) -> str:
    """Bounding box of LTItem if available, otherwise empty string"""
    if hasattr(o, 'bbox'):
        return ''.join(f'{i:<4.0f}' for i in o.bbox)
    return ''


def get_optional_text(o: Any) -> str:
    """Text of LTItem if available, otherwise empty string"""
    if hasattr(o, 'get_text'):
        return o.get_text().strip()
    return ''


path ='C:/Users/Stefan/Downloads/simple1.pdf'

pages = extract_pages(path)
show_ltitem_hierarchy(pages)
erzeugt die Ausgabe:

Code: Alles auswählen

element                        x1  y1  x2  y2   text
------------------------------ --- --- --- ---- -----
generator                       
  LTPage                       0   0   612 792  
    LTTextBoxHorizontal        100 695 161 719  Hello
      LTTextLineHorizontal     100 695 161 719  Hello
        LTChar                 100 695 117 719  H
        LTChar                 117 695 131 719  e
        LTChar                 131 695 136 719  l
        LTChar                 136 695 141 719  l
        LTChar                 141 695 155 719  o
        LTChar                 155 695 161 719  
        LTAnno                  
    LTTextBoxHorizontal        261 695 324 719  World
      LTTextLineHorizontal     261 695 324 719  World

wie muss das Script lauten um nur den Text von:

Code: Alles auswählen

LTTextBoxHorizontal        100 695 161 719 
auszugeben?

Danke - Stefan
Benutzeravatar
__blackjack__
User
Beiträge: 13117
Registriert: Samstag 2. Juni 2018, 10:21
Wohnort: 127.0.0.1
Kontaktdaten:

@Knollo: Du hast die Tutorials in der pdfminer.six-Dokumentation durchgearbeitet?

Das gezeigte Programm ist als Basis ja nicht wirklich brauchbar wenn man weiss was man sucht. Das ist ja allgemein um alle vorhandenen Objekte in der Hierarchie zu zeigen und verwendet Funktionen die nicht wissen was sie da bekommen. Du weisst das ja aber, da macht es keinen Sinn auf diesem allgemeinen Ansatz aufzubauen.

Was sind denn die Kriterien nach denen der Text ausgewählt werden soll? Inhalt? Position?

Ungetestet:

Code: Alles auswählen

#!/usr/bin/env python3
from pdfminer.high_level import extract_pages


def main():
    print(
        next(next(extract_pages("C:/Users/Stefan/Downloads/simple1.pdf")))
        .get_text()
        .strip()
    )


if __name__ == "__main__":
    main()
„All religions are the same: religion is basically guilt, with different holidays.” — Cathy Ladman
Knollo
User
Beiträge: 28
Registriert: Mittwoch 10. Juni 2020, 14:44

Hallo, aus der Dokumentation hab ich dem Beispiel ein 'id' zugefügt:
https://github.com/pdfminer/pdfminer.si ... _pages.rst

Code: Alles auswählen

from pdfminer.high_level import extract_pages
from pdfminer.layout import LTTextContainer
id = 0
for page_layout in extract_pages("C:/Users/Stefan/Downloads/simple1.pdf"):
    for element in page_layout:
        if isinstance(element, LTTextContainer):
            print ('ID: ' + str(id))
            print(element.get_text())
            id+=1
die erzeugte Ausgabe:

Code: Alles auswählen

ID: 0
Hello 

ID: 1
World

ID: 2
Hello 

ID: 3
World

ID: 4
H e l l o  

ID: 5
W o r l d

ID: 6
H e l l o  

ID: 7
W o r l d
so kann per 'id' der notwendige Text gefiltert werden. Das passt so :-)

Danke
Benutzeravatar
__blackjack__
User
Beiträge: 13117
Registriert: Samstag 2. Juni 2018, 10:21
Wohnort: 127.0.0.1
Kontaktdaten:

@Knollo: `id()` ist eine Funktion die man so verdeckt und es ist ja auch gar keine ID sondern ein Index zu den `LTTextContainer`-Objekten.
„All religions are the same: religion is basically guilt, with different holidays.” — Cathy Ladman
Antworten