[Kapitel 3] Einführung in Python mit 100 Klopfen Sprachverarbeitung

Dieser Artikel ist eine Fortsetzung meines Buches Einführung in Python mit 100 Knocking Language Processing. Ich werde [100 Schläge Kapitel 3] erklären (https://nlp100.github.io/ja/ch03.html).

In diesem Kapitel werden reguläre Ausdrücke verwendet. In Python wird es vom Modul "re" verwaltet. Um dieses Modul verwenden zu können, muss nicht nur der reguläre Ausdruck selbst, sondern auch die Methode und das Übereinstimmungsobjekt verstanden werden. Daher ist dies ziemlich schwierig. Ich denke nicht, dass es mehr ein Einstiegsniveau ist. Ich hatte nicht das Gefühl, einen besseren Kommentar als das Offizielle Tutorial schreiben zu können. Bitte lesen Sie ihn durch.

Kanonische Python-Ausdrücke sind jedoch langsam, daher versuche ich, sie so weit wie möglich zu vermeiden.

Laden Sie die Datei vorerst entsprechend herunter. * Diese Datei wird unter der nicht portablen Creative Commons Attribution-Inheritance 3.0-Lizenz verteilt. * *

$ wget https://nlp100.github.io/data/jawiki-country.json.gz

Gemäß der Problemstellung werden die Informationen eines Artikels pro Zeile im JSON-Format gespeichert. Das JSON-Format ist ein einfacher Export von Arrays und Wörterbüchern, und viele Programmiersprachen unterstützen dieses Format. Das Format dieser gesamten Datei heißt jedoch JSONL (JSON Lines). Schauen Sie sich den Inhalt der Datei mit $ gunzip -c jawiki-country.json.gz | less usw. an (möglicherweise sehen Sie ihn direkt mit less).

json Python hat auch eine Bibliothek, um diesen JSON einfach zu handhaben. Sein Name ist auch json. Dies ist ein Beispiel aus Dokument, aber es macht einen JSON-String zu einem Python-Objekt wie diesem und umgekehrt. Das ist sehr einfach.

import json
dic = json.loads('{"bar":["baz", null, 1.0, 2]}')
print(type(dic))
print(dic)
<class 'dict'>
{'bar': ['baz', None, 1.0, 2]}
dumped = json.dumps(dic)
print(type(dumped))
print(dumped)
<class 'str'>
{"bar": ["baz", null, 1.0, 2]}

Da es schwer zu verstehen war, habe ich auch den Typnamen mit "type ()" angezeigt. Übrigens bedeutet "s" in "Lades" und "Dumps" "String" anstelle von 3 Einheiten.

20. JSON-Daten lesen

Lesen Sie die JSON-Datei des Wikipedia-Artikels und zeigen Sie den Artikeltext zu "UK" an. Führen Sie in den Problemen 21-29 den hier extrahierten Artikeltext aus.

Die heruntergeladene Datei ist im gz-Format, aber ich möchte sie nicht so weit wie möglich erweitern. Es ist besser, es mit Pythons gzip-Modul zu lesen oder das Erweiterungsergebnis standardmäßig mit dem Unix-Befehl auszugeben und es mit einer Pipe zu verbinden.

Unten finden Sie ein Beispiel für die Antwort.

q20.py


import json
import sys


for line in sys.stdin:
    wiki_dict = json.loads(line)
    if wiki_dict['title'] == 'England':
        print(wiki_dict.get('text'))

$ gunzip -c jawiki-country.json.gz | python q20.py > uk.txt
$ head -n5 uk.txt
{{redirect|UK}}
 {{redirect|Vereinigtes Königreich|Ehrenländer im Frühjahr und Herbst|Englisch(Frühling und Herbst)}}
 {{Otheruses|Europäisches Land|Lokale Küche der Präfekturen Nagasaki und Kumamoto|Igirisu}}

{{Grundinformationsland Abkürzung = Vereinigtes Königreich

Ich kann Weiterleitungen und Artikel mit demselben Namen erhalten, aber es sollte kein Problem geben.

21. Extrahieren Sie Zeilen mit Kategorienamen

Extrahieren Sie die Zeile, in der der Kategoriename im Artikel angegeben ist.

Siehe die Wikipedia Markup-Kurzreferenz und den Inhalt der eigentlichen Datei Lass uns darüber nachdenken.

Es scheint genug zu sein, um die Zeilen zu extrahieren, die mit "[[Kategorie" "beginnen. str.startswith (Präfix) gibt den Wahrheitswert zurück, ob der String mit Präfix beginnt.

Unten finden Sie ein Beispiel für die Antwort.

q21.py


import sys


for line in sys.stdin:
    if line.startswith('[[Category'):
        print(line.rstrip())

(Ich erinnere mich, dass die Version 2015 eine Mischung aus Kleinbuchstaben war, aber in der Version 2020 ist sie weg ...)

22. Extraktion des Kategorienamens

Extrahieren Sie die Namen der Artikelkategorien (nach Namen, nicht zeilenweise).

Es wird so sein, wenn Sie Ihre Hände schneiden.

q22.py


import sys


for line in sys.stdin:
    print(line.lstrip("[Category:").rstrip("|*]\n"))

$ python q21.py < uk.txt | python q22.py

England Vereinigte Königreich Mitgliedsländer Königreich des Vereinigten Königreichs G8-Mitgliedsländer Mitgliedstaaten der Europäischen Union | Ehemalig Marine Nation Bestehendes souveränes Land Inselstaat Eine Nation / ein Gebiet, das 1801 gegründet wurde

23. Abschnittsstruktur

Zeigen Sie die im Artikel enthaltenen Abschnittsnamen und deren Ebenen an (z. B. 1, wenn "== Abschnittsname ==").

Ändern Sie == Ländername == in Ländername 1. Sie können das "Sub" in der Zeichenfolge mit "str.count (sub)" zählen.

Unten finden Sie ein Beispiel für eine Antwort, bei der keine regulären Ausdrücke verwendet werden.

q23.py


import sys

for line in sys.stdin:
    if line.startswith('=='):
        sec_name = line.strip('= \n')
        level = int(line.count('=')/2 - 1)
        print(sec_name, level)

24. Dateireferenzen extrahieren

Extrahieren Sie alle Mediendateien, auf die aus dem Artikel verwiesen wird.

Alle 2020 AusgabenDatei:Battle of Waterloo 1815.PNG|Es ist so geformt.|Verwenden Sie von nun an reguläre Ausdrücke, und beachten Sie, dass Sie sie entfernen möchten und dass sich möglicherweise mehr als einer in einer Zeile befindet. Das Testen regulärer Ausdrücke ist mit Online-Überprüfungswerkzeugen einfach.

Unten finden Sie ein Beispiel für die Antwort.

q24.py


import re
import sys

pat = re.compile(r'(Datei:)(?P<filename>.+?)\|')
for line in sys.stdin:
    for match in pat.finditer(line):
        print(match.group('filename'))

.+?\|In "Nach so wenigen Wiederholungen eines Charakters wie möglich|"Es bedeutet das. Bei der Betrachtung mehrerer Übereinstimmungenfinditer()Ist bequem. Wenn es keine Übereinstimmung gibt, an erster StelleforDer Satz dreht sich nicht.

Das gleiche Ergebnis kann erhalten werden, selbst wenn das Argument "Gruppe" 2 ist.

25. Vorlagen extrahieren

Extrahieren Sie die Feldnamen und Werte der im Artikel enthaltenen Vorlage "Basisinformationen" und speichern Sie sie als Wörterbuchobjekt.

Es ist schwierig, mit den Feldern umzugehen, die in der Vorlage fehlerhaft sind.

{{Grundlegende Informationen Land
|Kurzbezeichnung=England
|Japanischer Ländername=Vereinigtes Königreich Großbritannien und Nordirland
|Offizieller Ländername= {{lang|en|United Kingdom of Great Britain and Northern Ireland}}<ref>Offizieller Ländername außer Englisch:<br/>
*{{lang|gd|An Rìoghachd Aonaichte na Breatainn Mhòr agus Eirinn mu Thuath}}([[schottisch Gälisch]])<br/>
*{{lang|cy|Teyrnas Gyfunol Prydain Fawr a Gogledd Iwerddon}}([[Wales]])<br/>

Unten finden Sie ein Beispiel für die Antwort.

q25.py


import sys
import json


def main():
    dic = extract_baseinf(sys.stdin)
    sys.stdout.write(json.dumps(dic, ensure_ascii=False))


def extract_baseinf(fi):
    baseinf = {}
    isbaseinf = False
    for line in fi:
        if isbaseinf:
            if line.startswith('}}'):
                return baseinf

            elif line[0] == '|':
                templis = line.strip('|\n').split('=')
                key = templis[0].rstrip()
                value = "=".join(templis[1:]).lstrip()
                baseinf[key] = value
                
            else:
                value = line.rstrip('\n')
                baseinf[key] += f"\n{value}"

        elif line.startswith('{{Grundinformation'):
            isbaseinf = True


if __name__ == '__main__':
    main()

!python q25.py < uk.txt > uk_baseinf.json

Wenn es mehrere Zeilen umfasst, wird es durch Verketten verarbeitet.

Ich werde es einmal an json schreiben, da der Code im nächsten Problem kompliziert sein wird. Zu diesem Zeitpunkt werden Zeichen verstümmelt, es sei denn, "sure_ascii = False" wird verwendet.

26. Entfernen des markierten Markups

Entfernen Sie zum Zeitpunkt der Verarbeitung> 25 das MediaWiki-Hervorhebungsmarkup (alle schwachen Hervorhebungen, Hervorhebungen und starken Hervorhebungen) aus dem Vorlagenwert und konvertieren Sie es in Text (Referenz: [Markup-Kurzreferenz](http: // ja). wikipedia.org/wiki/Help:% E6% 97% A9% E8% A6% 8B% E8% A1% A8)).

Wenn ' 2, 3 oder 5 Mal hintereinander erscheint, löschen Sie es. In Bezug auf den regulären Ausdruck sieht es aus wie "r" {2,5}. +? "{2,5}", aber es ist schwer, es ernsthaft zu tun. Wenn Sie dies ohne reguläre Ausdrücke tun, sieht es wie üblich so aus.

q26.py


import json
import sys


def main():
    dic = json.loads(sys.stdin.read())
    dic = remove_emphasis(dic)
    print(json.dumps(dic, ensure_ascii=False, indent=4))

    
def remove_emphasis(dic):
    for key, value in dic.items():
        for n in (5, 3, 2):
            eliminated = value.split("'" * n)
            div, mod = divmod(len(eliminated), 2)
            if mod == 1 and div > 0:
                value = ''.join(eliminated)
                dic[key] = value
    return dic


if __name__ == '__main__':
    main()

Der Ablauf besteht darin, die in der vorherigen Frage erstellte JSON-Datei aus der Standardeingabe zu lesen und den Wert des Wörterbuchobjekts zu ändern. dict.items () ist ein Iterator, der eine Reihe von (Schlüssel, Wert) Paaren im Wörterbuch zurückgibt. Erinnern wir uns daran.

Wenn Sie "" in einem Zeichenfolgenliteral verwenden möchten, müssen Sie es maskieren oder in "" einschließen. Um dieselbe Zeichenfolge zusammenhängend zu machen, können Sie sie mit einem ganzzahligen Vielfachen multiplizieren. Und "split ()" Ich versuche, "" zu löschen und zu beurteilen, ob die Anzahl der Elemente in der zurückgegebenen Liste ungerade ist, damit ich keine unregelmäßigen "wie" a''b "lösche. Sie kann mit "%" berechnet werden, kann aber auch dann belassen werden, wenn der Quotient 0 ist. Wenn Sie also die integrierte Funktion "divmod ()" verwenden, werden der Quotient und der Rest gleichzeitig berechnet.

Der bedingte Ausdruck "A und B" ist für mich neu, aber Sie können ihn sehen, indem Sie ihn betrachten. Gleiches gilt für oder. Wichtig ist die Bewertungsstrategie. Wenn sich herausstellt, dass "A und B" "A == Falsch" ist, endet die Auswertung des Ausdrucks ohne Auswertung von "B". Daher ist es effizienter, "A" wahrscheinlicher als "B" zu machen. In ähnlicher Weise bewertet "A" oder "B" "B" nicht, wenn sich herausstellt, dass es "A == Wahr" ist. Schreiben Sie also einen Ausdruck in "A", der eher "Wahr" ist.

27. Entfernung interner Links

Entfernen Sie zusätzlich zur Verarbeitung 26 das interne Link-Markup von MediaWiki aus dem Vorlagenwert und konvertieren Sie es in Text (Referenz: [Markup-Kurzreferenz](https://ja.wikipedia.org/wiki/Help :)). % E6% 97% A9% E8% A6% 8B% E8% A1% A8)).

Da es 3 Muster gibt, werden wir reguläre Ausdrücke verwenden.

q27.py


"""
[[Artikelüberschrift]]
[[Artikelüberschrift|Zeichen anzeigen]]
[[Artikelüberschrift#Abteilungsname|Zeichen anzeigen]] 
"""
import json
import re
import sys


from q26 import remove_emphasis


def main():
    dic = json.loads(sys.stdin.read())
    dic = remove_emphasis(dic)
    dic = remove_link(dic)
    print(json.dumps(dic, ensure_ascii=False, indent=4))


def remove_link(dic):
    pat = re.compile(r"""
        \[\[        # [[
        ([^|]+\|)*  #Artikelüberschrift|Nicht oder wiederholt
        ([^]]+)     #Ersetzen Sie den Teil, der dem Anzeigezeichen pat entspricht, durch diesen
        \]\]        # ]]
    """, re.VERBOSE)
    for key, value in dic.items():
        value = pat.sub(r'\2', value)
        dic[key] = value
    return dic

if __name__ == '__main__':
    main()

Nach der Bearbeitung der vorherigen Frage können Sie den Wert des Wörterbuchs erneut ändern.

Sie können ein Zeichenfolgenliteral schreiben, das mehrere Zeilen umfasst, indem Sie es in dreifache Anführungszeichen setzen. Außerdem werden bei "re.VERBOSE" Leerzeichen, Zeilenumbrüche und Kommentare im regulären Ausdruck ignoriert, aber es ist immer noch schwer zu erkennen ...

Der Teil von "pat" (r "\ 2", Wert) bedeutet, den Teil von "Wert", der mit "pat" übereinstimmt, durch "Gruppe (2)" des Übereinstimmungsobjekts zu ersetzen. ..

28. Entfernen des MediaWiki-Markups

Entfernen Sie zusätzlich zum> 27-Prozess MediaWiki-Markups so weit wie möglich aus den Vorlagenwerten und formatieren Sie grundlegende Länderinformationen.

Sie können es mit Pandoc und Pypandoc tun ... Wenn Sie mit regulären Ausdrücken Ihr Bestes geben, sollten Sie das hervorgehobene Markup, interne Links, Dateiverweise, externe Links, <ref>, <br />, {{0}}, nur reguläre Ausdrücke, löschen. Ich werde es sagen ...

basic_info = re.compile(r"\|(.+?)\s=\s(.+)")
emphasize = re.compile(r"('+){2,5}(.+?)('+){2,5}")
link_inner = re.compile(r"\[\[(.+?)\]\]")
file_ref = re.compile(r"\[\[Datei:.+?\|.+?\|(.+?)\]\]")
ref = re.compile(r"<ref((\s.+?)>|(>.+?)</ref>)")
link_website = re.compile(r"\[.+?\]")
lang_template = re.compile(r"{{.+?\|.+?\|(.+?)}}")
br = re.compile(r"<.+?>")
space = re.compile(r"{{0}}")

29. Rufen Sie die URL des Flaggenbildes ab

Verwenden Sie den Inhalt der Vorlage, um die URL des Flaggenbilds abzurufen. (Hinweis: MediaWiki API imageinfo .2F_ii) kann aufgerufen werden, um den Dateiverweis in eine URL zu konvertieren)

Es scheint, dass Sie "https: // commons.wikimedia.org / w / api.php" mit verschiedenen Parametern (Dateiname usw.) anfordern sollten. Wenn Sie "Media Wiki API Image Info" usw. googeln, werden die Parameter angezeigt. Sie können "urllib" verwenden, um die API mit dem Python-Standardmodul aufzurufen. In der Dokumentation Verwendungsbeispiele heißt es: "Im Folgenden finden Sie eine Beispielsitzung zum Abrufen einer URL mit Parametern mithilfe der GET-Methode. Sie können dies tun, indem Sie sich den Teil "is:" ansehen.

Unten finden Sie ein Beispiel für die Antwort.

q29.py


import json
import sys
from urllib import request, parse
import re


baseinf = json.loads(sys.stdin.read())

url = 'https://commons.wikimedia.org/w/api.php'
params = {'action': 'query', 'prop': 'imageinfo', 'iiprop': 'url',
            'format': 'json', 'titles': f'File:{baseinf["Flaggenbild"]}'}

req = request.Request(f'{url}?{parse.urlencode(params)}')
with request.urlopen(req) as res:
    body = res.read()

# print(body['query']['pages']['347935']['imageinfo'][0]['url'])
print(re.search(r'"url":"(.+?)"', body.decode()).group(1))
!python q29.py < uk_baseinf.json
https://upload.wikimedia.org/wikipedia/commons/a/ae/Flag_of_the_United_Kingdom.svg

Da die zurückgegebene JSON-Datei kompliziert ist, ist es praktischer, nach dem URL-ähnlichen Teil zu suchen. Aus irgendeinem Grund war body eine Byte-Zeichenfolge, daher funktionierte es nur, wenn ich es dekodierte.

Zusammenfassung

Weiter ist Kapitel 4

Persönlich war dieses Kapitel schmerzhaft. Ist es wie NLP vom nächsten Mal?

Nächstes Kapitel

Recommended Posts

[Kapitel 5] Einführung in Python mit 100 Klopfen Sprachverarbeitung
[Kapitel 3] Einführung in Python mit 100 Klopfen Sprachverarbeitung
[Kapitel 2] Einführung in Python mit 100 Klopfen Sprachverarbeitung
[Kapitel 4] Einführung in Python mit 100 Klopfen Sprachverarbeitung
[Kapitel 6] Einführung in Scicit-Learn mit 100 Klopfen Sprachverarbeitung
100 Sprachverarbeitungsklopfen mit Python (Kapitel 1)
100 Sprachverarbeitungsklopfen mit Python (Kapitel 3)
100 Sprachverarbeitungsklopfen mit Python (Kapitel 2, Teil 2)
100 Sprachverarbeitungsklopfen mit Python (Kapitel 2, Teil 1)
100 Sprachverarbeitungsklopfen ~ Kapitel 1
Einführung in die Python-Sprache
100 Sprachverarbeitung klopft Kapitel 2 (10 ~ 19)
Erste Schritte mit Python mit 100 Klopfen bei der Sprachverarbeitung
100 Sprachverarbeitungsklopfen mit Python 2015
100 Sprachverarbeitung Knock Kapitel 2 (Python)
Rehabilitation von Python- und NLP-Kenntnissen ab "100 Language Processing Knock 2015" (Kapitel 1)
Einführung in die verteilte Parallelverarbeitung von Python durch Ray
Ich habe versucht, die 2020-Version von 100 Sprachverarbeitungsproblemen zu lösen [Kapitel 3: Reguläre Ausdrücke 20 bis 24]
Ich habe versucht, die 2020-Version von 100 Sprachverarbeitungsproblemen zu lösen [Kapitel 1: Vorbereitungsbewegung 00-04]
Ich habe versucht, die 2020-Version von 100 Sprachverarbeitungsproblemen zu lösen [Kapitel 1: Vorbereitungsbewegung 05-09]
[Sprachverarbeitung 100 Schläge 2020] Kapitel 3: Reguläre Ausdrücke
100 Sprachverarbeitung Knock Kapitel 1 in Python
100 Sprachverarbeitungsklopfen 2020: Kapitel 4 (morphologische Analyse)
[Sprachverarbeitung 100 Schläge 2020] Kapitel 5: Abhängigkeitsanalyse
[Einführung in Python3 Tag 13] Kapitel 7 Zeichenfolgen (7.1-7.1.1.1)
Einführung in Protobuf-c (C-Sprache ⇔ Python)
[Sprachverarbeitung 100 Schläge 2020] Kapitel 1: Vorbereitende Bewegung
Die Bildverarbeitung mit Python 100 klopft an die Binärisierung Nr. 3
[Sprachverarbeitung 100 Schläge 2020] Kapitel 7: Wortvektor
10 Funktionen von "Sprache mit Batterie" Python
100 Sprachverarbeitung klopfen 2020: Kapitel 3 (regulärer Ausdruck)
[Sprachverarbeitung 100 Schläge 2020] Kapitel 8: Neuronales Netz
[Sprachverarbeitung 100 Schläge 2020] Kapitel 2: UNIX-Befehle
[Sprachverarbeitung 100 Schläge 2020] Kapitel 9: RNN, CNN
100 Bildverarbeitung mit Python Knock # 2 Graustufen
100 Sprachverarbeitung Knock Kapitel 1 von Python
[Sprachverarbeitung 100 Schläge 2020] Kapitel 4: Morphologische Analyse
[Einführung in Python3 Tag 21] Kapitel 10 System (10.1 bis 10.5)
Sprachverarbeitung 100 Schläge-48: Extraktion des Weges von der Nase zur Wurzel
[Raspi4; Einführung in den Sound] Stabile Aufzeichnung der Toneingabe mit Python ♪
Rehabilitation von Python- und NLP-Kenntnissen ab "Knock 100 Language Processing 2015" (Kapitel 2, zweite Hälfte)
Rehabilitation von Python- und NLP-Kenntnissen ab "100 Language Processing Knock 2015" (Kapitel 2, erste Hälfte)
100 Sprachverarbeitungsklopfen (2020): 40
Grundlagen der binärisierten Bildverarbeitung durch Python
100 Sprachverarbeitungsklopfen (2020): 32
Ich habe mit GiNZA v3.1 Kapitel 4 100 Sprachverarbeitungsklopfen 2020 durchgeführt
100 Sprachverarbeitungsklopfen (2020): 35
100 Sprachverarbeitungsklopfen (2020): 47
100 Sprachverarbeitungsklopfen (2020): 39
[Einführung in Python3, Tag 17] Kapitel 8 Datenziele (8.1-8.2.5)
Kapitel 4 Zusammenfassung der Einführung in Entwurfsmuster, die in Java gelernt wurden
100 Sprachverarbeitungsklopfen (2020): 22
100 Sprachverarbeitung Knock-22: Extraktion des Kategorienamens
100 Sprachverarbeitungsklopfen (2020): 26
100 Sprachverarbeitungsklopfen (2020): 34
[Einführung in Python3, Tag 17] Kapitel 8 Datenziele (8.3-8.3.6.1)
100 Bildverarbeitung mit Python Knock # 8 Max Pooling
100 Sprachverarbeitungsklopfen (2020): 42
Einführung in das Auffüllen von Python-Bildern Auffüllen von Bildern mit ImageDataGenerator