Nach vorherigen dachte ich, dass diese Reparatur notwendig ist, also ist es eine einfache Fortsetzung.
Es ist in Ordnung, die PDF-Seite im CSV-Format auszugeben, aber ich sagte, es handele sich um eine Menge Demo-Daten. Insbesondere kam der Untertitel in die Mitte. Es ist nüchtern und schmerzhaft.
Als ich kein ähnliches Projekt finden konnte, fand ich die folgende Seite. Analyse der Liste der schwarzen Unternehmen des Ministeriums für Gesundheit, Arbeit und Soziales mit Python (PDFMiner.six)
Ich wusste, dass ich einen Kameraden hatte und mit den Koordinaten auskommen konnte. Also werde ich es versuchen.
Referenz: Wählen Sie PDFMiner aus, um Textinformationen aus PDF zu extrahieren
Es scheint, dass pdfminer auch die Koordinateninformationen des Layouts abrufen kann. Bisher wurden mit TextConverter nur Zeichendaten extrahiert. In PDFPageAggregator scheinen Koordinaten und Zeichendaten herausgezogen zu sein. Verwenden Sie diese Option.
Überprüfen Sie vorerst, welche Koordinaten verfügbar sind. Es tut mir leid, dass ich das Beispiel-PDF nicht vorbereiten konnte ...
from pdfminer.pdfinterp import PDFResourceManager, PDFPageInterpreter
from pdfminer.converter import TextConverter, PDFPageAggregator
from pdfminer.layout import LAParams, LTContainer, LTTextBox, LTTextLine, LTChar
from pdfminer.pdfpage import PDFPage
def convert_pdf_to_txt(self,p_d_f):
fp = open(p_d_f, 'rb')
for page in PDFPage.get_pages(fp):
rsrcmgr = PDFResourceManager()
laparams = LAParams()
laparams.detect_vertical = True
device = PDFPageAggregator(rsrcmgr, laparams=laparams)
interpreter = PDFPageInterpreter(rsrcmgr, device)
#Holen Sie sich Koordinaten und Zeichendaten aus PDF
interpreter.process_page(page)
layout = device.get_result()
#Anzeige von Koordinaten und Zeichen
for node in layout:
if isinstance(node, LTTextBox) or isinstance(node, LTTextLine):
print(node.get_text()) #Brief
word =input(node.bbox) #Koordinate
word =input("---page end---")
Ein ineffizienter Typ, der an der Eingabeaufforderung nachschaut.
Um ehrlich zu sein, verstehe ich das Urteil nicht wirklich wie LTTextBox, aber ich habe es als Magie eingesetzt. Lass es uns richtig herausfinden.
Dies ist ein Auszug aus dem Ausgabeergebnis. Der Text ist Dummy.
---page end---
Über Popcornmaschine
(68.28, 765.90036, 337.2, 779.9403599999999)
Es ist eine Maschine, die Popcorn knallt und herstellt.
(67.8, 697.71564, 410.4000000000001, 718.47564)
Bitte seien Sie vorsichtig, wenn Sie es verwenden.
(67.8, 665.29564, 339.8400000000002, 686.05564)
Die Verwendung ist wie folgt.
(67.8, 643.69564, 279.3600000000001, 653.65564000)
Erläuterung
(67.8, 730.11564, 87.96000000000001, 740.07564)
Taple ist die Koordinate. Die Reihenfolge ist (x0, y0, x1, y1). Einzelheiten finden Sie auf der Referenzseite! Einfach ausgedrückt, wenn Sie sich y1 ansehen, können Sie die Koordinaten der Zeichen von unten sehen. Mit anderen Worten, wenn y1 auf der Seite in absteigender Reihenfolge ist, werden die Zeichen in der Reihenfolge von oben angeordnet = richtige Anordnungsform (in diesem Fall).
Wenn man dieses Ausgabeergebnis betrachtet, ist y1 in der letzten Zeile das zweitgrößte, daher ist es ein irrelevantes Ergebnis unter dem Gesichtspunkt, einfach von oben anzuordnen. Es kann basierend auf x0 sortiert werden. Ich weiß nichts Es scheint, dass die Koordinaten gut genommen sind, also werde ich etwas mit diesem y1 machen.
① Erstellen Sie ein Wörterbuch ② Sortieren Sie das Wörterbuch (Schlüssel in absteigender Reihenfolge) ③ Machen Sie es zu einer Zeichenkette ④ Zeilenumbrüche bereinigen
Das sollte funktionieren. Wenn Sie eine schlaue Person sind, schauen Sie sich bitte nur das fertige Produkt an.
d=[]
for node in layout:
if isinstance(node, LTTextBox) or isinstance(node, LTTextLine):
y1 = node.bbox[3]
#Wenn es sich um eine Tabelle handelt, werden die Koordinaten von y1 dupliziert
if y1 in d:
d[y1] += "|" + node.get_text()
else:
d[y1] = node.get_text()
Erstellen Sie ein schnelles Wörterbuch mit Koordinaten und Zeichen. Ich ergreife auch Tischmaßnahmen, um mich zu entspannen.
Aber um ehrlich zu sein, ist diese Methode, es zu öffnen, eine unfruchtbare Anstrengung, weil es Löcher hat. Der Grund dafür ist, dass die obigen Koordinaten Zeichen Zeile für Zeile zu nehmen scheinen, aber der Mechanismus besteht darin, einen Randauffüllungs-ähnlichen Wert festzulegen und in naher Zukunft einen Zeichenblock als "Block" zu verwenden. Es scheint, dass es (sicherlich) ist.
Solide Geschichte: Wenn Sie nichts festlegen, wird der Standardrand angewendet und mehrere Zeilen werden als ein Block in Sätzen mit engen Zeilenabständen und feinen Tabellen erkannt. Wenn Sie also mehrere Zeichenzeilen mit denselben Koordinaten erhalten, ist dies bereits ein Zusammenbruch der Ese-Tabellenoperation.
Wenn ja, spreche ich davon, die Randauffüllung richtig einzustellen, aber diesmal habe ich nicht so viel verlangt, deshalb werde ich sie nicht besonders einstellen. Wenn der Tisch herauskommt, versuchen wir es mit dem Gefühl "Es tut mir leid!"
Referenz: Zusammenfassung der Python-Sortierung (Liste, Wörterbuchtyp, Serie, Datenrahmen)
d2 = sorted(d.items(), key=lambda x: -x[0])
Ich habs gemacht! Ramuda Hatsuyoshi! Wenn Sie dies tun, wird das Wörterbuch übrigens eine Liste sein. Es ist mir egal, solange ich sortieren kann.
text = ""
for d0 in d2:
text += d0[1]
Es ist nur rund und rund.
Referenz: Kommagetrennte Zeichenfolgen mit Python teilen, Leerzeichen und Liste teilen, entfernen Ich bin dir immer zu Dank verpflichtet.
space = re.compile("[ ]+")
text = re.sub(space, "", text )
l_text = [a for a in text.splitlines() if a != '']
text = '\n'.join(l_text).replace('\n|', '|')
Es gibt viele Leerzeichen und Zeilenumbrüche. Dies ist eine Lösung für das Problem. Ersetzen Sie Leerzeichen und löschen Sie Zeilenumbrüche als Liste. Übrigens wird auch der Zeilenumbruch vor dem Symbol gelöscht, das bei der Rückkehr zur Tabelle als Markierung verwendet wurde.
from pdfminer.pdfinterp import PDFResourceManager, PDFPageInterpreter
from pdfminer.converter import TextConverter, PDFPageAggregator
from pdfminer.layout import LAParams, LTContainer, LTTextBox, LTTextLine, LTChar
from pdfminer.pdfpage import PDFPage
import csv,re,datetime
import pandas as pd
class converter(object):
def convert_pdf_to_txt(self,p_d_f):
print("system:pdf【" + p_d_f + "] Ist gelesen")
df = pd.DataFrame(columns=["Datum und Uhrzeit aktualisieren","Satz","Seitennummer"])
cnt = 1
space = re.compile("[ ]+")
fp = open(p_d_f, 'rb')
#Extrahieren Sie Koordinaten und Zeichendaten aus dem PDF
for page in PDFPage.get_pages(fp):
rsrcmgr = PDFResourceManager()
laparams = LAParams()
laparams.detect_vertical = True
device = PDFPageAggregator(rsrcmgr, laparams=laparams)
interpreter = PDFPageInterpreter(rsrcmgr, device)
#Holen Sie sich Koordinaten und Zeichendaten aus PDF
interpreter.process_page(page)
layout = device.get_result()
#Erstellen Sie ein Wörterbuch mit Koordinaten und Daten
d={}
for node in layout:
if isinstance(node, LTTextBox) or isinstance(node, LTTextLine):
y1 = node.bbox[3]
#Wenn es sich um eine Tabelle handelt, werden die Koordinaten von y1 dupliziert
if y1 in d:
d[y1] += "|" + node.get_text()
else:
d.update({y1 : node.get_text()})
#Nach Koordinaten sortieren
d2 = sorted(d.items(), key=lambda x: -x[0])
#Stoßen Sie gegen eine Schnur
text = ""
for d0 in d2:
text += ddd[1]
#Leere Zeilenumbrüche entfernen
text = re.sub(space, "", text)
l_text = [a for a in text.splitlines() if a != '']
text = '\n'.join(l_text).replace('\n|', '|')
df.loc[cnt,["Satz","Seitennummer"]] = [text,cnt]
cnt += 1
fp.close()
device.close()
now = datetime.datetime.now()
df["Datum und Uhrzeit aktualisieren"] = now
csv_path = p_d_f.replace('.pdf', '.csv')
with open(csv_path, mode='w', encoding='cp932', errors='ignore', newline='\n') as f:
df.to_csv(f,index=False)
if __name__ == "__main__":
p_d_f = "Irgendwie.pdf"
con=converter()
hoge=con.pdf_to_csv(p_d_f)
Ich habe es nicht gut überprüft, weil ich es vom letzten Mal addiert und subtrahiert habe, aber etwas Ähnliches hat funktioniert. Wenn Sie einen Fehler erhalten, beheben Sie ihn bitte selbst.
Recommended Posts