@ninaebez: Das ist nicht lauffähig weil `dateiname`, `suchbegriff`, und `datei` nicht definiert sind. Und bei `outputFilename` wird versucht etwas mit `format()` in eine Zeichenkette zu formatieren, die gar keinen Platzhalter dafür hat.
Auf Modulebene sollte nur Code stehen der Konstanten, Funktionen, und Klassen definiert. Das Hauptprogramm steht üblicherweise in einer Funktion die `main()` heisst.
Es gibt so einige Schlechte Namen. `liste` — der Leser will wissen was die Bedeutung der Werte ist, nicht das es eine Liste ist. Zudem muss es das nicht, es könnte auch eine beliebige andere Sequenz sein. Darum schreibt man keine Grunddatentypen in Namen.
`x`, `i`, `z`, `y` sind schlechte Namen weil einbuchstabige Namen sehr selten gut sind, weil die einfach nichts über die Bedeutung sagen. Wenn man zu `x` den Kommentar ``# Anzahl der Dokumente`` schreiben muss, dann sollte der Kommentar weg und `x` sollte `document_count` heissen. Schon versteht man nicht nur wo der Kommentar steht was sich hinter dem Namen verbirgt, sondern überall wo der Name steht/verwendet wird. Konkret bei diesen Namen ist auch schlecht das die manchmal sogar sinnvoll sind, weil sie zu den wenigen Ausnahmen gehören die eine erkennbare Bedeutung haben, hier aber für etwas anderes verwendet werden. `i` ist ein typischer Laufindex, und `x`, `y`, und `z` sind gute Namen für Koordinaten.
Wobei `document_count` beziehungsweise Anzahl der Dokumente nicht stimmt. Das ist ja gar nicht die Anzahl der Dokumente sondern die Nummer des aktuellen Dokuments. Und statt das manuell hoch zu zählen, wo der Leser erst einmal schauen und verstehen muss, dass das tatsächlich bedingungslos hochgezählt wird, würde man das mit `enumerate()` erzeugen.
`i` verstehe ich nicht. Wozu ist das gut? Das ist auch die Gesamtzahl der verarbeiteten Seiten. Also sollte den gleichen Wert haben wie ``liste[-1]``, warum wird das noch mal zusätzlich gezählt wenn man den Wert einfacher haben kann.
Es wird anscheinend auch nicht am Suchbegriff getrennt, in dem Sinne das am Ende auch alle Seiten in den neuen PDFs sind, sondern es werden neue PDFs erzeugt die immer bis zu einer Seite mit Suchbegriff gehen. Das sind dann nur in dem Fall alle Seiten wenn der Suchbegriff auch auf der letzten Seite vorkommt.
Wobei ich da sowieso Probleme habe die Logik nachzuvollziehen. Es wird beispielsweise die Seitennummer der letzten Fundstelle mit der Seitennummer der ersten Fundstelle verrechnet was keinen Sinn micht. Dir Irrsinn würde Auffallen wenn man `z` sinnvoll benennt und dann die Bedingung ``page_count < 0`` liest. Eine Anzahl kann nicht negativ sein. Diese ganze rumidexierei sollte man verständlicher schreiben, ohne das man da so rumrechnen muss. Beispielsweise in dem man sich was passendes aus `more_itertools` sucht.
`sollseite` sollte wohl eigentlich `page` heissen. Und `page` sollte `page_number` heissen.
`y` wird zu früh definiert. Das wird ja nur im ``else``-Zweig überhaupt benötigt. Und dort ist die ``while``-Schleife eigentlich eine ``for``-Schleife, so dass man diese Zuweisung an `y` überhaupt nicht braucht.
`str()` und ``+`` um Zeichenketten und Werte zusammenzustückeln ist eher BASIC denn Python. In Python gibt es dafür Zeichenkettenformatierung mit der `format()`-Methode und f-Zeichenkettenliterale.
Der Code fällt auf die Nase falls der Suchbegriff auf keiner Seite gefunden wird, und ich bin mir nicht sicher, dass er fehlerfrei funktioniert falls nur *eine* Seite gefunden wird.
Was soll der Name `fp` bedeuten?
In `search_pdf()` kann man das Erstellen der Liste als „list comprehension“ ausdrücken.
`rsrcmgr`? Srsly?
Zwischenstand (ungetestet):
Code: Alles auswählen
#!/usr/bin/env python3
from io import StringIO
import PyPDF2
from pdfminer.converter import TextConverter
from pdfminer.layout import LAParams
from pdfminer.pdfinterp import PDFPageInterpreter, PDFResourceManager
from pdfminer.pdfpage import PDFPage
def get_page_content(page):
resource_manager = PDFResourceManager()
out_file = StringIO()
PDFPageInterpreter(
resource_manager,
TextConverter(resource_manager, out_file, laparams=LAParams()),
).process_page(page)
return out_file.getvalue()
def search_pdf(pdf_filename, search_string):
with open(pdf_filename, "rb") as file:
return [
page_number
for page_number, page in enumerate(PDFPage.get_pages(file), 1)
if search_string in get_page_content(page)
]
def main():
dateiname = "..."
suchbegriff = "..."
page_numbers = search_pdf(dateiname, suchbegriff)
written_page_count = 0
if page_numbers:
reader = PyPDF2.PdfFileReader(dateiname)
#
# TODO This iterating over `page_numbers` and mixing index access in the
# loop is confusing and most likely can be written simpler and easier
# to understand.
#
for document_index, page_number in enumerate(page_numbers):
writer = PyPDF2.PdfFileWriter()
page_count = (
page_numbers[document_index] - page_numbers[document_index - 1]
)
if page_count == 1 or page_count < 0:
writer.addPage(reader.getPage(page_number - 1))
written_page_count += 1
else:
for offset in range(page_count):
writer.addPage(
reader.getPage(
page_numbers[document_index - 1] + offset
)
)
written_page_count += page_count
output_filename = f"NEU{document_index}_{dateiname}"
with open(output_filename, "wb") as file:
writer.write(file)
print("created", output_filename)
print(
"Das Dokument hatte ursprünglich",
page_numbers[-1],
"Seiten. Es wurde zerteilt in",
document_index + 1,
"Dokumente mit insgesamt",
written_page_count,
"Seiten.",
)
else:
print(f"Keine Fundstellen von {suchbegriff!r} gefunden.")
if __name__ == "__main__":
main()