[PYTHON] Untersuchen Sie mit Wiktionary unregelmäßige Verben auf Englisch

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.

  1. Erkundung effizienter Verarbeitungsmethoden für Wiktionary
  2. Vergleichen Sie die Wiktionary-Verarbeitungsgeschwindigkeit zwischen F # und Python
  3. Untersuchen Sie unregelmäßige Verben auf Englisch mit Wiktionary ← Dieser Artikel

Das Skript für diesen Artikel befindet sich im folgenden Repository.

Überblick

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.

Verbinformationen

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.

Überschrift

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.

Es scheint, dass die Hierarchie der Überschriften nicht immer einheitlich ist.

Skript

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

Datenformung

Formatieren Sie die erfassten Daten so, dass sie einfach zu verarbeiten sind.

Entfernen Sie Links und Kommentare

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}}

Entfernung zusätzlicher Informationen

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|-}}

Regelmäßiges Verb

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.

Übersicht über Wortformen

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.

  1. Es gibt keine Beschreibung der früheren Form.
  2. Die vergangene Form und der letzte Teil haben dieselbe Form und enden mit ed.
  3. Das ursprüngliche Formular endet mit e, und das vorherige Formular fügt dem ursprünglichen Formular d hinzu.
  4. Das ursprüngliche Formular endet mit y, und das vorherige Formular ändert y in i und fügt ed hinzu.
  5. Fügen Sie für das vergangene Formular ed zum ursprünglichen Formular hinzu.
  6. Fügen Sie für das vergangene Formular ed hinzu, indem Sie das letzte Zeichen des ursprünglichen Formulars duplizieren. (Am Ende c folgt ein Wort k)

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

Entfernung des gleichen Musters

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.

Anwendung

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.

Recommended Posts

Untersuchen Sie mit Wiktionary unregelmäßige Verben auf Englisch
Untersuchen Sie Speicherlecks mit objgraph