Sie können jetzt den vollständigen Text von Wiktionary in ca. 1 Minute untersuchen. Als Beispiel für das Extrahieren aussagekräftiger Informationen werden wir unregelmäßige Verben auf Englisch untersuchen.
Dies ist eine Reihe von Artikeln.
Das Skript für diesen Artikel befindet sich im folgenden Repository.
Da es schwierig ist, die gesamten riesigen Speicherauszugsdaten zu erfassen, werden wir sie grob eingrenzen und mit der Verarbeitung fortfahren.
Lesen Sie zuerst den vollständigen Text und sammeln Sie Verbinformationen.
Analysieren Sie die erhaltenen Informationen und entfernen Sie die regulären Verben in mehreren Schritten.
Nehmen wir als Beispiel, wie Varianten englischer Verben gespeichert werden.
Verb
see (third-person singular simple present sees, present participle seeing, simple past saw or (dialectal) seen or (dialectal) seent or (dialectal) seed, past participle seen or (dialectal) seent or (dialectal) seed)
Da es in Sätzen geschrieben ist und es auch andere Formen von Informationen wie Diallektal gibt, scheint es schwierig, dies programmatisch zu analysieren.
Wenn Sie die Quelle überprüfen, hat sie ein Format, das einfach zu handhaben ist.
====Verb====
{{en-verb|sees|seeing|saw|past2=seen|past2_qual=dialectal|past3=seent|past3_qual=dialectal|past4=seed|past4_qual=dialectal|seen|past_ptc2=seent|past_ptc2_qual=dialectal|past_ptc3=seed|past_ptc3_qual=dialectal}}
Es scheint, dass Sie zusätzliche Informationen wie "past2 =" ignorieren können. Die folgenden Informationen bleiben erhalten.
{{en-verb|sees|seeing|saw|seen}}
Das Originalformular scheint aus dem Titel der Seite zu stammen.
Ich bestätigte die Überschrift, die von Gleichen umgeben ist.
Es gibt keine Fälle, in denen die Anzahl der Gleichen links und rechts nicht übereinstimmt, aber es scheint, dass Leerzeichen vorhanden sind.
[Beispiel] Leerzeichen werden durch Unterstriche angezeigt.
== Japanese == _
(letztes Leerzeichen)
==== _ Übersetzungen _ ====
(Leerzeichen zwischen gleich)
Da ein solches Muster ein kleiner Teil des Ganzen ist, scheint es ursprünglich keinen Platz zu geben. Da sogar ein Teil davon vorhanden ist, müssen Maßnahmen ergriffen werden.
Es scheint, dass die Hierarchie der Überschriften nicht immer einheitlich ist.
===Verb===
In Python implementiert.
Extrahieren Sie Titel, ID und Text als Seiteninformationen.
def getpages(bz2data):
xml = bz2.decompress(bz2data).decode("utf-8")
pages = ET.fromstring(f"<pages>{xml}</pages>")
for page in pages:
if int(page.find("ns").text) == 0:
title = page.find("title").text
id = int(page.find("id").text)
with io.StringIO(page.find("revision/text").text) as text:
yield id, title, text
Teilen Sie "Text" nach Muster.
def splittext(pattern, text):
line = next(text, "")
while line:
m = pattern.match(line)
line = next(text, "")
if m:
def g():
nonlocal line
while line and not pattern.match(line):
yield line
line = next(text, "")
yield m[1].strip(), g()
Sammle das {{en-verb ...}}
bei ==== Verb ====
von == English ==
. Schließen Sie Stichwörter aus, die Leerzeichen oder Bindestriche als zusammengesetzte Wörter oder zusammengesetzte Wörter enthalten.
def en_verb(args):
target, pos, length = args
with open(target, "rb") as f:
f.seek(pos)
bz2data = f.read(length)
pattern1 = re.compile("==([^=].*)==")
pattern2 = re.compile("===+([^=].*?)===")
result = []
for id, title, text in getpages(bz2data):
if " " in title or "-" in title: continue
for lang, text2 in splittext(pattern1, text):
if lang != "English": continue
for subsub, text3 in splittext(pattern2, text2):
if subsub != "Verb": continue
for line in text3:
if line.startswith("{{en-verb"):
result.append((id, title, line.strip()))
break
return result
Fügen Sie dazu Parallelverarbeitung und Dateiausgabe hinzu. Ich habe das ganze Skript unten gestellt.
Führen Sie das Skript aus und überprüfen Sie die Anzahl der Zeilen der Ausgabedaten.
Ausführungsergebnis
$ time python en-verb.py
6,861 / 6,861
real 1m50.159s
user 13m53.906s
sys 0m17.438s
$ wc -l en-verb.tsv
31334 en-verb.tsv
Formatieren Sie die erfassten Daten so, dass sie einfach zu verarbeiten sind.
Wenn Sie sich die erfassten Daten ansehen, finden Sie Links und Kommentare.
$ grep "\[" en-verb.tsv | head -n 2
4109 U-turn {{en-verb|head=[[U]]-[[turn]]|U-turns|U-turning|U-turned}}
5661 read {{en-verb|reads|reading|[[:en:#Etymology_2|read]]|[[:en:#Etymology_2|read]]|past_ptc2=readen|past_ptc2_qual=archaic, dialectal}}
$ grep '<!--' en-verb.tsv | head -n 2
5443 sing {{en-verb|sings|singing|sang|sung|past_ptc2=sungen|past_ptc2_qual=archaic}}<!--Sang or sung for preterite, according to AHD.-->
6959 hide {{en-verb|hides|hiding|hided}}<!--not hid, hidden!-->
Entfernen Sie die Klammern und Kommentare zum Link. Mit einem Link[[:en:#Etymology_2|read]]
Innen wie|
Was durch getrennt ist, ist das letzte Element (in diesem Beispielread
) Bleibt übrig.
en-verb-2.py
import re, sys
pattern1 = re.compile("\[\[(.+?)\]\]")
pattern2 = re.compile("<!--(.*?)-->")
for line in sys.stdin:
while (m := pattern1.search(line)):
data = m[1].split("|")
line = line[:m.start()] + data[-1] + line[m.end():]
sys.stdout.write(pattern2("", line))
Ausführungsergebnis
$ python en-verb-2.py < en-verb.tsv > en-verb-2.tsv
$ diff -U 0 en-verb.tsv en-verb-2.tsv | head -n 8
--- en-verb.tsv 2020-06-12 21:22:01.943343500 +0900
+++ en-verb-2.tsv 2020-06-12 21:22:54.506793900 +0900
@@ -747 +747 @@
-5443 sing {{en-verb|sings|singing|sang|sung|past_ptc2=sungen|past_ptc2_qual=archaic}}<!--Sang or sung for preterite, according to AHD.-->
+5443 sing {{en-verb|sings|singing|sang|sung|past_ptc2=sungen|past_ptc2_qual=archaic}}
@@ -763 +763 @@
-5661 read {{en-verb|reads|reading|[[:en:#Etymology_2|read]]|[[:en:#Etymology_2|read]]|past_ptc2=readen|past_ptc2_qual=archaic, dialectal}}
+5661 read {{en-verb|reads|reading|read|read|past_ptc2=readen|past_ptc2_qual=archaic, dialectal}}
Zusätzliche Informationen wie "past_ptc2 = readen" beim Lesen werden benötigt, wenn Sie Dialekte oder älteres Material betrachten, aber dieses Mal werden wir es entfernen. Entfernen Sie alle anderen Informationen nach }}
.
en-verb-3.py
import re, sys
pattern1 = re.compile("{{(.*?)}}")
pattern2 = re.compile("[a-z0-9_]+?=")
for line in sys.stdin:
if (m := pattern1.search(line)):
data = [d for d in m[1].split("|") if not pattern2.match(d)]
line = line[:m.start()] + "{{" + "|".join(data) + "}}\n"
sys.stdout.write(line)
Ausführungsergebnis
$ python en-verb-3.py < en-verb-2.tsv > en-verb-3.tsv
$ diff -U 0 en-verb-2.tsv en-verb-3.tsv | head -n 8
--- en-verb-2.tsv 2020-06-12 21:22:54.506793900 +0900
+++ en-verb-3.tsv 2020-06-12 21:25:39.197882200 +0900
@@ -14 +14 @@
-71 crow {{en-verb|crows|crowing|crowed|past2=crew|past2_qual=UK|crowed|past_ptc2=crown|past_ptc2_qual=archaic}}
+71 crow {{en-verb|crows|crowing|crowed|crowed}}
@@ -19 +19 @@
-114 may {{en-verb|may|-|might|-|past_ptc2=mought|past_ptc2_qual=obsolete}}
+114 may {{en-verb|may|-|might|-}}
Dieses Mal besteht der Zweck darin, unregelmäßige Verben zu untersuchen, sodass reguläre Verben ausgeschlossen werden.
Lassen Sie uns überprüfen, wie ein reguläres Verb aus den zuvor generierten Daten geschrieben wird.
2157 open {{en-verb}}
46912 like {{en-verb|lik}}
58007 wish {{en-verb|es}}
60426 hone {{en-verb|hon|es}}
34295 chop {{en-verb|chop|p|ing}}
39760 compel {{en-verb|compel|l|ed}}
Dies scheint folgendes zu bedeuten. Bindestrich ist ein Trennzeichen zwischen dem Stiel und dem Ende.
Wort | 3 einfach | Aktueller Teil | Partizip Perfekt | Interpretation |
---|---|---|---|---|
open | open-s | open-ing | open-ed | Keine Wortforminformationen |
like | like-s | lik-ing | lik-ed | Die letzten beiden Wörter mögen |
wish | wish-es | wish-ing | wish-ed | 3 einfache es |
hone | hon-es | hon-ing | hon-ed | Wortstamm hon und 3 einheitliche es |
chop | chop-s | chop-p-ing | chop-p-ed | Dupliziere p und die aktuelle Trennung |
compel | compel-s | compel-l-ing | compel-l-ed | Duplikat l und vergangene Form ed |
Like und Hone haben das gleiche Muster, aber beide Stile scheinen das gleiche Ergebnis zu liefern. Die Position des Bindestrichs ist unterschiedlich, hat jedoch keine sprachliche Bedeutung und ist für ein Programm vorgesehen, das Varianten generiert.
Entfernen Sie Wörter ohne zusätzliche Informationen, bis zu 2 Begriffe oder 3 Elemente. Entfernen Sie auch den Anfang "{{en-verb |" und das Ende "}}", um sie durch Tabulatoren zu trennen.
en-verb-4.py
import re, sys
pattern = re.compile("{{en-verb\\|(.*?)\\|*}}")
for line in sys.stdin:
id, verb, forms = line.split("\t")
if (m := pattern.match(forms)):
forms = m[1].split("|")
if len(forms) > 2 and forms[2] != "ing" and forms[2] != "ed":
forms = "\t".join(forms)
print(f"{id}\t{verb}\t{forms}")
Ausführungsergebnis
$ python en-verb-4.py < en-verb-3.tsv > en-verb-4.tsv
$ head -n 5 en-verb-4.tsv
71 crow crows crowing crowed crowed
112 march marches marching marched
114 may may - might -
167 swop swops swopping swopped
180 deal deals dealing dealt
$ wc -l en-verb-4.tsv
5296 en-verb-4.tsv
Ich habe es bis zu einem gewissen Grad eingegrenzt, aber es gibt immer noch viele.
Wenn man sich die Daten ansieht, scheint es, dass die Notation, die den Stamm angibt, nicht einheitlich ist und reguläre Verben gemischt werden.
71 crow crows crowing crowed crowed
167 swop swops swopping swopped
3 Ignorieren Sie die Informationen einfacher und vorhandener Teile und anderer Formen und schließen Sie diejenigen aus, die die folgenden Bedingungen erfüllen, als reguläre Verben.
Es gibt Bedingungen für doppelte Zeichen, aber diesmal ist es nicht notwendig, also werde ich nicht eingeben.
Wörter mit Apostrophie werden durch Entfernen des Symbols beurteilt.
127005 F F's|F'ing|F'ed
Wenn die vergangene Form und der vergangene Teil sowohl -
als auch undefiniert sind, werden sie entfernt.
en-verb-5.py
import sys
for line in sys.stdin:
id, *forms = line.strip().split("\t")
if len(forms) == 4: forms.append(forms[3])
verb, _, _, past, pp = [f.replace("'", "").replace("-", "") for f in forms]
if past == pp:
if not past: continue
if past.endswith("ed"):
if verb.endswith("e") and verb + "d" == past: continue
if verb.endswith("y") and verb[:-1] + "ied" == past: continue
if verb + "ed" == past: continue
if verb + verb[-1] + "ed" == past: continue
if verb[-1] == "c" and verb + "ked" == past: continue
forms = "\t".join(forms)
print(f"{id}\t{forms}")
Ausführungsergebnis
$ python en-verb-5.py < en-verb-4.tsv > en-verb-5.tsv
$ wc -l en-verb-5.tsv
1461 en-verb-5.tsv
Wenn Sie sich die Daten ansehen, sehen Sie möglicherweise dasselbe Wort mehrmals in einer Reihe.
5438 think thinks thinking thought thought
5438 think thinks thinking thought thought
Darüber hinaus gibt es einige zusammengesetzte Wörter, die das gleiche Änderungsmuster aufweisen.
5664 draw draws drawing drew drawn
7404 overdraw overdraws overdrawing overdrew overdrawn
7761 withdraw withdraws withdrawing withdrew withdrawn
Kombinieren Sie dieselben Wörter zu einem und schränken Sie dasselbe Muster auf nur kurze Wörter ein.
en-verb-6.py
import sys
verbs = {}
for line in sys.stdin:
id, verb, *forms = line.strip().split("\t")
if verb in verbs: continue
verbs[verb] = (id, forms)
verbs2 = []
for v1, (id, forms) in verbs.items():
contains = False
for v2, (_, f2) in verbs.items():
if v1 != v2 and v1.endswith(v2):
c = True
for f1, f2 in zip(forms, f2):
if not f1.endswith(f2):
c = False
break
if c:
contains = True
break
if not contains:
forms = "\t".join(forms)
print(f"{id}\t{v1}\t{forms}")
Ausführungsergebnis
$ python en-verb-6.py < en-verb-5.tsv > en-verb-6.tsv
$ wc -l en-verb-6.tsv
378 en-verb-6.tsv
Es wurde erheblich zusammengedrückt. Danach wäre es realistisch, sie einzeln zu betrachten.
Platzieren Sie die erstellte Datei. Es gibt noch einige Probleme, aber es scheint, dass die Originaldaten geändert werden müssen.
Mit dieser Methode können Sie andere Sprachen als Englisch untersuchen. Natürlich ist Wiktionary nicht die einzige Informationsquelle, aber es ist ein guter Anfang, da die Informationen gesammelt werden, sobald Sie das Programm schreiben.
Wenn Sie eine neue Sprache lernen, kann dies hilfreich sein, um Materialien zum Selbststudium zu erstellen.
Wenn ich etwas versuche, werde ich es hinzufügen.