"Erstellen eines Dienstes, der den Nutzungsverlauf von Suica für Mobilgeräte so bearbeitet, dass er problemlos zur Kostenabrechnung verwendet werden kann" Letztes Mal habe ich mit Docker eine Ausführungsumgebung erstellt Klicken Sie hier für das fertige Produkt https://www.mobilesuica.work
tabula-py tabula-py Zunächst habe ich das leicht versucht
test.py
import tabula
import pandas as pd
df = tabula.read_pdf('a.pdf')
print(df.head())
Leider war es ein Fehler
AttributeError: 'list' object has no attribute 'head'
Anscheinend wird es in einem Array zurückgegeben Wenn ja, sollte ich das tun?
test.py
df = tabula.read_pdf('a.pdf')
print(df[0].head())
Es wurde gemacht (der resultierende Stationsname hat sich geändert)
Datumstyp Art der verwendeten Station.1 Station verwendet.1 Bilanzdifferenz
0 2 6 Wiederholen Sie NaN NaN NaN\9,753 NaN
2 2 7 Betreten Sie Tokio. Verlassen Sie Yokohama\9,573 -180
3 2 7 Yokohama betreten Verlassen Sie Tokio\9,393 -180
Standardmäßig wird nur die erste Seite verwendet. Fügen Sie also pages = 'all' hinzu und kombinieren Sie die beiden Seiten. Die maximale Nutzungshistorie von Mobile Suica beträgt 100, und wenn sie zurückgestellt wird, gibt es 101, und wenn sie in PDF konvertiert wird, sind es bis zu 2 Seiten.
test.py
df = tabula.read_pdf('a.pdf',pages='all')
for i in range(len(df)):
print(f"{i+1}Auf der Seite{len(df[i])}Es gibt eine Linie")
Ausführungsergebnis
(app-root) bash-4.2# python3 test.py
Es gibt 51 Zeilen auf einer Seite
Es gibt 50 Zeilen auf 2 Seiten
Sie können sehen, dass die erste Seite eine weitere Zeile für "Zurückgestellt" enthält. Da es schwierig ist, sie zu behandeln, wenn sie getrennt sind, verwenden wir ein DataFrmae. Verwenden Sie concat.
test.py
df = tabula.read_pdf('a.pdf',pages='all')
d = pd.concat(df,ignore_index=True)
print(f"{len(d)}Es gibt eine Linie")
Ausführungsergebnis
(app-root) bash-4.2# python3 test.py
Es gibt 101 Zeilen
** ignore_index = True **, aber wenn Sie dies nicht angeben, ist der Index keine ordnungsgemäße Seriennummer. Lass uns vergleichen.
ignore_index = True Keine Der Index kehrt an der Grenze zwischen der 1. und 2. Seite auf 0 zurück
50 3 4 Geben Sie Tokio ein. Verlassen Sie Yokohama\9,443 -180
0 3 5 Bargeld NaN NaN NaN\9,543 100
ignore_index = True Ja Es ist eine Seriennummer wie sie ist
50 3 4 Geben Sie Tokio ein. Verlassen Sie Yokohama\9,443 -180
51 3 5 Bargeld NaN NaN NaN\9,543 100
Wenn Sie so weit gehen, können Sie dasselbe mit mehreren Dateien tun. Es gibt auch convert_into_by_batch in tabula-py, aber es ist etwas schwierig zu verwenden, da es so ist, als würde man ein Verzeichnis angeben und die PDF-Dateien darunter sammeln. (Da ich nur einen Nutzungsverlauf hatte, habe ich dieselbe Datei viele Male gelesen.)
test.py
fileList = ['a.pdf','a.pdf','a.pdf']
dfList = []
for fileName in fileList:
df = tabula.read_pdf(fileName,pages='all')
for i in range(len(df)):
dfList.append(df[i])
d = pd.concat(dfList,ignore_index=True)
print(f"{len(d)}Es gibt eine Linie")
Ausführungsergebnis
(app-root) bash-4.2# python3 test.py
Es gibt 303 Zeilen
Bisher ist mir aufgefallen, dass es einen kleinen Unterschied zwischen der ersten und der zweiten Seite gibt.
Ladungsteil auf der ersten Seite
24 2 21 Bargeld NaN NaN NaN\9,883 +100
Ladungsteil auf der zweiten Seite
78 3 21 Bargeld NaN NaN NaN\10,317 100
Auf der zweiten Seite befindet sich kein "+". Ich kann es problemlos in Bezug auf die Datenverarbeitung tun, aber es fühlt sich schlecht an. Als ich es nachgeschlagen habe, war es der Unterschied, ob es als Zahl (zweite Seite) oder als Zeichen (erste Seite) erkannt wurde.
14 2 15 Bus usw. OKK NaN NaN\9,103 -2,000
Wenn es mehr als 3 Stellen hat, wird Thousand Separator (,) eingefügt, sodass anscheinend alle Seiten als Zeichen erkannt werden. Seite 2 wurde als Nummer erkannt, weil sie nicht vorhanden war (alle weniger als 3 Ziffern). Da es bequemer ist, es so zu nehmen, wie es ist, habe ich mit Pandas gesucht und festgestellt, dass ** dtype = 'object' ** verwendet werden sollte. tabula-py ist eine großartige Möglichkeit, Pandas-Optionen so wie sie sind zu übergeben. Das Endergebnis ist wie folgt.
test.py
fileList = ['a.pdf','a.pdf','a.pdf']
dfList = []
for fileName in fileList:
df = tabula.read_pdf(fileName,pages='all',pandas_options={'dtype':'object'})
for i in range(len(df)):
dfList.append(df[i])
d = pd.concat(dfList,ignore_index=True)
Es ist erstaunlich, dass Sie damit eine PDF-Tabelle in einen DataFrame ablegen können.