Phyton Programieren

Installation und Anwendung von Datenbankschnittstellen wie SQLite, PostgreSQL, MariaDB/MySQL, der DB-API 2.0 und sonstigen Datenbanksystemen.
Antworten
enzoilias
User
Beiträge: 1
Registriert: Donnerstag 16. März 2023, 22:14

Hallo ich ahbe eine Frage, ich versuche etwas zu programieren,

ich habe pdfs Datei und ich möchte ein Paar serie extrahieren und im Excel datei suchen, wenn die Serien gefunden würden , würde dokemmntnumer extrahieren und in Excel Dateil in einer Spalte q übertragen,
ich ahbe versucht, aber leider könnte ich das ist cod
kann man mir helfen

import PyPDF2
import re
import pandas as pd
import os


folder_path = r'C:\Users\ubc\Desktop'
excel_file = r'C:\Users\ubc\HKW22_Gesamt-KKS-Liste.xlsx'


pattern = re.compile(r'[A-Z][0-9]{12}')

def extract_text(filename):
with open(os.path.join(folder_path, filename), 'rb') as f:
reader = PyPDF2.PdfFileReader(f)
text = ''
for i in range(reader.getNumPages()):
text += reader.getPage(i).extractText()
return text




def extract_doc_num(text):
match = re.search(r'Dok\.-Nr:\s*([A-Z0-9]{13})', text)
if match:
return match.group(1)
else:
return None

pdf_files = [f for f in os.listdir(folder_path) if f.endswith('.pdf')]

results = []

for filename in pdf_files:
text = extract_text(filename)
if text:
doc_num = extract_doc_num(text)
found = re.findall(pattern, text)
if found:
for s in found:
for i, row in df.iterrows():
if row['A'] == s:
results.append((filename, s, doc_num))
df.loc[i, 'Q'] = doc_num

df_results = pd.DataFrame(results, columns=['Dateiname', 'Seriennummer', 'Dokumentennummer'])
df.to_excel(os.path.join(folder_path, excel_file), index=False)
Benutzeravatar
__blackjack__
User
Beiträge: 13100
Registriert: Samstag 2. Juni 2018, 10:21
Wohnort: 127.0.0.1
Kontaktdaten:

enzoilias: Der Code ist so sicher nicht durchgelaufen weil dort `df` verwendet wird, was nirgends definiert ist.

Auf Modulebene sollte nur Code stehen der Konstanten, Funktionen, und Klassen definiert. Das Hauptprogramm steht üblicherweise in einer Funktion die `main()` heisst.

Konstantennamen werden per Konvention KOMPLETT_GROSS geschrieben.

Statt `os.listdir()` und `os.path` verwendet man in neuem Code das `pathlib`-Modul.

`pattern` ist der Name vom Argument von `re.compile()` also für Zeichenketten die reguläre Ausdrücke als Text enthalten, und damit kein guter Name für einen kompilierten regulären Ausdruck. Ähnlich bei `files` — Dateien sind etwas anderes als Datei*namen*.

`PdfFileReader` ist veraltet und durch `PdfReader` ersetzt.

Auch `PdfFileReader` hätte man schon einen Dateipfad übergeben können — das öffnen der Datei muss man nicht vorher selber machen.

Die Methoden `getNumPages()`, `getPage()`, und `extractText()` sind auch veraltet. Es gibt ein `pages`-Attribut das eine Länge hat, und die Seiten haben eine `extract_text()`-Methode. Die Seitenanzahl braucht man aber auch gar nicht, weil man direkt über das `pages`-Attribut iterieren kann.

Wiederholtes ``+=`` mit Zeichenketten in einer Schleife ist potentiell sehr ineffizient. Der idiomatische Weg ist das Sammeln der Einzelteile in einer Liste die dann mit der `join()`-Methode von Zeichenketten zu einer Zeichenkette zusammengefügt wird. Oder man wendet die Methode auf ein iterierbares Objekt mit den Teilzeichenketten an. Und man fügt da besser ein Leerzeichen zwischen den Teilzeichenketten ein, sonst ergibt das letzte Wort auf einer Seite zusammen mit dem ersten Wort der Folgeseite ein zusammengesetztes Wort. Oder was auch immer da jeweils steht.

``if text:`` und ``if found:`` sind überflüssig, weil bei jeweils leeren Objekten der folgende Code keinen Effekt hat.

Namen sollten keine kryptischen Abkürzungen enthalten oder gar nur daraus bestehen. Der Name soll dem Leser vermitteln was der Wert dahinter im Programm bedeutet, nicht zum rätseln zwingen. `s` ist kein guter Name für eine Seriennummer.

In einer Schleife über die Zeilen eines DataFrame zu iterieren ist in der Regel falsch. Pandas verwendet man ja gerade damit man so etwas nicht machen muss.

Falls die Seriennummer in dem `DataFrame` eindeutig ist, sollte das der Index sein.

`os.path.join()` mit zwei absoluten Pfaden macht keinen Sinn.

Zwischenstand (ungetestet):

Code: Alles auswählen

#!/usr/bin/env python3
import re
from pathlib import Path

import pandas as pd
from PyPDF2 import PdfReader

FOLDER_PATH = Path(R"C:\Users\ubc\Desktop")
EXCEL_FILEPATH = Path(R"C:\Users\ubc\HKW22_Gesamt-KKS-Liste.xlsx")
SERIAL_NUMBER_RE = re.compile(r"[A-Z][0-9]{12}")


def extract_text(file_path):
    return " ".join(page.extract_text() for page in PdfReader(file_path).pages)


def extract_document_number(text):
    match = re.search(r"Dok\.-Nr:\s*([A-Z0-9]{13})", text)
    return match.group(1) if match else None


def main():
    results = []
    for pdf_file_path in FOLDER_PATH.glob("*.pdf"):
        text = extract_text(pdf_file_path)
        document_number = extract_document_number(text)
        for serial_number in re.findall(SERIAL_NUMBER_RE, text):
            #
            # FIXME Das ist ziemlich sicher eine falsche Verwendung von Pandas.
            #
            for i, row in df.iterrows():
                if row["A"] == serial_number:
                    results.append(
                        (pdf_file_path.name, serial_number, document_number)
                    )
                    df.loc[i, "Q"] = document_number

    df_results = pd.DataFrame(
        results, columns=["Dateiname", "Seriennummer", "Dokumentennummer"]
    )
    df.to_excel(EXCEL_FILEPATH, index=False)


if __name__ == "__main__":
    main()
„All religions are the same: religion is basically guilt, with different holidays.” — Cathy Ladman
Antworten