Vous pouvez maintenant étudier le texte intégral du Wiktionnaire en 1 minute environ. À titre d'exemple pour extraire des informations significatives, nous étudierons les verbes irréguliers en anglais.
Ceci est une série d'articles.
Le script de cet article est publié dans le référentiel suivant.
Comme il est difficile de saisir l'intégralité des données de vidage énormes, nous allons les réduire grossièrement et procéder au traitement.
Tout d'abord, lisez le texte intégral et collectez des informations verbales.
Analysez les informations obtenues et supprimez les verbes réguliers en plusieurs étapes.
Prenons un exemple pour voir comment les variantes des verbes anglais sont stockées.
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)
Comme il est écrit en phrases et qu'il existe également d'autres formes d'informations telles que diallectales, il semble difficile de les analyser par programme.
Si vous vérifiez la source, elle est dans un format facile à gérer.
====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}}
Il semble que vous puissiez ignorer des informations supplémentaires telles que past2 =
. Les informations suivantes demeurent.
{{en-verb|sees|seeing|saw|seen}}
Le formulaire original semble provenir du titre de la page.
J'ai confirmé le cap entouré d'égal à égal.
Il n'y a aucun cas où le nombre d'égaux ne correspond pas à gauche et à droite, mais il semble qu'il puisse y avoir des espaces.
[Exemple] Les espaces sont indiqués par des traits de soulignement.
== Japonais == _
(dernier espace)
==== _ Translations _ ====
(espace entre égaux)
Puisqu'un tel modèle est une petite partie de l'ensemble, il semble qu'il n'y ait pas d'espace à l'origine. Même une partie de celui-ci existe, il est donc nécessaire de prendre des mesures.
Il semble que la hiérarchie des rubriques ne soit pas toujours unifiée.
===Verb===
Implémenté en Python.
Extrayez le titre, l'identifiant et le texte comme informations sur la page.
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
Divisez le «texte» par motif.
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()
Récupérez le {{en-verb ...}}
à ==== Verb ====
de == English ==
. Excluez les mots-clés contenant des espaces ou des traits d'union en tant que mots composés ou mots composés.
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
Ajoutez à cela un traitement parallèle et une sortie de fichier. J'ai mis tout le script ci-dessous.
Exécutez le script et vérifiez le nombre de lignes de données de sortie.
Résultat d'exécution
$ 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
Formatez les données acquises de manière à ce qu'elles soient faciles à traiter.
Si vous regardez les données acquises, vous trouverez des liens et des commentaires.
$ 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!-->
Supprimez les parenthèses et les commentaires sur le lien. Avec un lien[[:en:#Etymology_2|read]]
À l'intérieur comme|
Ce qui est séparé par est le dernier élément (dans cet exempleread
) Est laissé.
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))
Résultat d'exécution
$ 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}}
Des informations supplémentaires telles que past_ptc2 = readen
en lecture sont nécessaires si vous regardez des dialectes ou des documents plus anciens, mais cette fois, nous les supprimerons. Supprimez toute autre information après «}}».
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)
Résultat d'exécution
$ 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|-}}
Cette fois, le but est d'étudier les verbes irréguliers, nous allons donc exclure les verbes réguliers.
Voyons comment écrire un verbe régulier à partir des données générées précédemment.
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}}
Cela semble vouloir dire ce qui suit. Le trait d'union est un délimiteur entre la tige et la fin.
mot | 3 simples | Partie courante | Participe passé | Interprétation |
---|---|---|---|---|
open | open-s | open-ing | open-ed | Aucune information sous forme de mot |
like | like-s | lik-ing | lik-ed | Les deux derniers mots lik |
wish | wish-es | wish-ing | wish-ed | 3 simples es |
hone | hon-es | hon-ing | hon-ed | Mot racine hon et 3 es unitaires |
chop | chop-s | chop-p-ing | chop-p-ed | Dupliquer p et la séparation actuelle |
compel | compel-s | compel-l-ing | compel-l-ed | Dupliquer l et le passé |
Like et Hone ont le même motif, mais les deux styles semblent donner le même résultat. Les tirets sont dans des positions différentes, mais ils n'ont aucune signification linguistique et sont destinés aux programmes générant des variantes.
Supprimez les mots sans informations supplémentaires, jusqu'à 2 termes ou 3 éléments ou éditions. Supprimez également le début {{en-verb |
et la fin }}
pour les délimiter par des tabulations.
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}")
Résultat d'exécution
$ 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
Je l'ai réduit dans une certaine mesure, mais il y en a encore beaucoup.
En regardant les données, il semble que la notation qui spécifie la racine n'est pas unifiée et que les verbes réguliers sont mélangés.
71 crow crows crowing crowed crowed
167 swop swops swopping swopped
3 Ignorez les informations des parties et variantes simples et présentes et excluez celles qui satisfont aux conditions suivantes en tant que verbes réguliers.
Il y a des conditions pour les caractères en double, mais cette fois ce n'est pas nécessaire, donc je n'entrerai pas.
Les mots avec apostrophie sont jugés en supprimant le symbole.
127005 F F's|F'ing|F'ed
Si la forme passée et la partie passée sont à la fois «-» et non définies, elles seront supprimées.
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}")
Résultat d'exécution
$ python en-verb-5.py < en-verb-4.tsv > en-verb-5.tsv
$ wc -l en-verb-5.tsv
1461 en-verb-5.tsv
Si vous regardez les données, vous pouvez voir le même mot aligné plusieurs fois.
5438 think thinks thinking thought thought
5438 think thinks thinking thought thought
De plus, certains mots composés ont le même schéma de changement.
5664 draw draws drawing drew drawn
7404 overdraw overdraws overdrawing overdrew overdrawn
7761 withdraw withdraws withdrawing withdrew withdrawn
Combinez les mêmes mots en un seul et réduisez le même modèle aux mots courts.
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}")
Résultat d'exécution
$ python en-verb-6.py < en-verb-5.tsv > en-verb-6.tsv
$ wc -l en-verb-6.tsv
378 en-verb-6.tsv
Il a été considérablement serré. Après cela, il serait réaliste de les examiner individuellement.
Placez le fichier créé. Il y a encore quelques problèmes, mais il semble que les données d'origine devront être modifiées.
En appliquant cette méthode, vous pouvez rechercher des langues autres que l'anglais. Bien sûr, Wiktionary n'est pas la seule source d'informations, mais c'est un bon point de départ car les informations sont collectées dès que vous écrivez le programme.
Lors de l'apprentissage d'une nouvelle langue, cela peut être utile pour créer du matériel d'auto-apprentissage.
Si j'essaye quelque chose, je l'ajouterai.