[PYTHON] J'ai essayé 100 traitements linguistiques Knock 2020: Chapitre 3

introduction

J'ai essayé Language processing 100 knock 2020. Vous pouvez voir le lien des autres chapitres d'ici, et le code source de ici.

Chapitre 3 Expressions régulières

N ° 20 Lecture des données JSON

Lisez le fichier JSON de l'article Wikipedia et affichez le texte de l'article sur "UK". Dans les problèmes 21-29, exécutez sur le texte de l'article extrait ici.

<détails>

Réponse </ summary>

020.py


import pandas as pd

path = "jawiki-country.json.gz"
df = pd.read_json(path, lines=True)
print(df.query("title == 'Angleterre'")["text"].values[0])

# -> {{redirect|UK}}
#    {{redirect|Royaume-Uni|Pays honorables au printemps et à l'automne|Anglais(Printemps et automne)}}
#    {{Otheruses|pays européen|Cuisine locale des préfectures de Nagasaki et Kumamoto|Igirisu}}
Commentaires

Puisque le fichier donné est au format «JSON Lines», nous définissons «lines» sur «True». Vous pouvez obtenir des éléments de ligne qui remplissent les conditions en utilisant query (). Vous pouvez également faire df [df [" title "] =" UK "].

No.21 Lignes d'extrait contenant les noms de catégories

Extrayez la ligne qui déclare le nom de la catégorie dans l'article.

<détails>

Réponse </ summary>

021.py


import input_json as js

article = js.input()
print(list(filter(lambda x: "[[Category" in x, article)))

# -> ['[[Category:Angleterre|*]]', '[[Category:Angleterre連邦加盟国]]', '[[Category:Royaume du Royaume-Uni|*]]'...
Commentaires

L'instruction extraite au n ° 20 peut être appelée par ʻimportetjs.input (). La fonction filterrenvoie-t-elle un itérateur, non? J'ai l'impression que le traitement delist (filter ())` ne va pas bien. Je me demande s'il existe une autre méthode de mise en œuvre.

N ° 22 Extraction du nom de la catégorie

Extraire les noms des catégories d'articles (par nom, pas ligne par ligne).

<détails>

Réponse </ summary>

022.py



import input_json as js
import re

article = js.input()
list = [re.match("\[\[Category:([^\|,\]]+)", item) for item in article]
print([str.groups()[0] for str in list if str is not None])

# -> ['Angleterre', 'Angleterre連邦加盟国', 'Royaume du Royaume-Uni'...
Commentaires

J'ai remarqué que le titre dans ce chapitre était une expression régulière, donc je l'ai écrit en l'utilisant. Extraction de la chaîne de caractères entre «[[Category:» et «|» ou «]». C'est comme un code et c'est amusant. Si vous utilisez groups (), vous obtiendrez le contenu de () dans l'expression régulière comme un type multiple, donc je les ai mis ensemble dans un type de liste.

Structure de section n ° 23

Affichez le nom de la section et son niveau (par exemple, 1 si "== nom de la section ==") inclus dans l'article.

<détails>

Réponse </ summary>

023.py


import input_json as js
import re

article = js.input()
list = [re.search("(==+)([^=]*)", item) for item in article]
print([{item.group(2): f'Level {item.group(1).count("=")}'} for item in list if not item == None])

# -> [{'Nom du pays': 'Level 2'}, {'histoire': 'Level 2'}...
Commentaires

J'ai obtenu les parties == + et [^ =] * de l'expression régulière avec search (). Group (). Le niveau de la section correspondait donc au nombre de =, alors j'ai essayé de le mettre ensemble dans le type dict en utilisant count ().

N ° 24 Extraction de la référence du dossier

Extrayez tous les fichiers multimédias référencés dans l'article.

<détails>

Réponse </ summary>

024.py


import input_json as js
import re

article = js.input()
list = [re.search("^\[\[Fichier:([^|]*)", item) for item in article]
print([str.group(1) for str in list if not str==None])

# -> ['Descriptio Prime Tabulae Europae.jpg', "Lenepveu, Jeanne d'Arc au siège d'Orléans.jpg "...
Commentaires

En consultant la Référence rapide du balisage, [[File: On a l'impression que la partie commençant par est un fichier multimédia. J'ai également recherché une chaîne de caractères contenant [[File:, mais je l'ai exclue car cela semble peu probable.

Extraction du modèle n ° 25

Extraire les noms de champs et les valeurs du modèle «informations de base» inclus dans l'article et les stocker comme objet dictionnaire.

<détails>

Réponse </ summary>

025.py


import pandas as pd
import re

df = pd.read_json("jawiki-country.json.gz", lines=True)
article = df.query("title == 'Angleterre'")["text"].values[0]
str = re.findall("(?<=Informations de base Pays\n\|).*(?=\n\}\})", article,  flags=re.DOTALL)
ans = {}
for item in str[0].replace(" ", "").split("\n|"):
    kv = re.sub("\<ref\>.*\</ref\>", "", item, flags=re.DOTALL).split("=")
    ans[kv[0]] = kv[1]
print(ans)

# -> {'Nom abrégé': 'Angleterre', 'Nom du pays japonais': 'Royaume-Uni de Grande-Bretagne et d'Irlande du Nord',...
Commentaires

La partie qui commence par {{informations de base et se termine par \ n}} ʻest assortie d'une anticipation affirmative et d'une anticipation affirmative, et split se fait avec \ n | . Vous devez définir l'indicateur re.DOTALL car vous devez inclure \ n` dans l'instruction de correspondance. Ce problème a pris un certain temps ...

N ° 26 Suppression du balisage accentué

Au moment du traitement> 25, supprimez le balisage d'accentuation MediaWiki (tous d'accentuation faible, d'accentuation et d'accentuation forte) de la valeur du modèle et convertissez-le en texte (Référence: Tableau de référence rapide du balisage).

<détails>

Réponse </ summary>

026.py


import pandas as pd
import re


def remove_quote(a: list):
    ans = {}
    for i in a:
        i = re.sub("'+", "", i, flags=re.DOTALL)
        i = re.sub("<br/>", "", i, flags=re.DOTALL).split("=")
        ans[i[0]]= i[1]
    return ans


df = pd.read_json("jawiki-country.json.gz", lines=True)
article = df.query("title == 'Angleterre'")["text"].values[0]
str = re.findall("(?<=Informations de base Pays\n\|).*(?=\n\}\})", article, flags=re.DOTALL)
list = [re.sub("\<ref\>.*\</ref\>", "", item, flags=re.DOTALL) for item in str[0].replace(" ", "").split("\n|")]
print(remove_quote(list))

# -> ...'Slogan': '{{lang|fr|[[Dieuetmondroit]]}}([[français]]:[[Dieuetmondroit|Dieu et mes droits]])',...
Commentaires

Supprimé `` '' et <br /> de la sortie du n ° 25. Il semble que le type puisse être spécifié dans l'argument de la fonction, j'ai donc essayé de l'utiliser.

N ° 27 Suppression des liens internes

En plus du traitement de> 26, supprimez le balisage du lien interne MediaWiki de la valeur du modèle et convertissez-le en texte (Référence: Tableau de référence rapide du balisage).

<détails>

Réponse </ summary>

027.py


import pandas as pd
import re

p_quote = re.compile("'+")
p_br = re.compile("<br/>")
p_ref = re.compile("\<ref\>.*\</ref\>", re.DOTALL)
p_emphasis1 = re.compile("\[\[[^\]]*\|([^\|]*?)\]\]")
p_emphasis2 = re.compile("\[\[(.+?)\]\]")


def remove_markup(a: list):
    ans = {}
    for i in a:
        i = p_quote.sub("", i)
        i = p_br.sub("", i)
        i = p_emphasis1.sub(r"\1", i)
        if p_emphasis2.search(i):
            i = i.replace("[", "").replace("]", "")
        i = i.split("=")
        ans[i[0]] = i[1]
    return ans


df = pd.read_json("jawiki-country.json.gz", lines=True)
article = df.query("title == 'Angleterre'")["text"].values[0]
str = re.findall("(?<=Informations de base Pays\n\|).*(?=\n\}\})", article, flags=re.DOTALL)
list = [p_ref.sub("", item) for item in str[0].replace(" ", "").split("\n|")]
print(remove_markup(list))

# -> ...'Slogan': '{{lang|fr|Dieuetmondroit}}(Français:Dieu et mes droits)'...
Commentaires

[A]Celui en forme deA,[A|...|B]Celui en forme deBEst sortie. J'ai également pré-compilé et utilisé des expressions régulières. Peu à peu, je ne comprends pas l'expression régulière.

De plus, j'ai pensé après avoir vu la réponse ci-dessus, mais si vous savez, faites-moi savoir si vous pouvez résoudre le phénomène selon lequel l'arrangement des couleurs devient étrange lorsque vous intégrez une expression régulière.

No.28 Suppression du balisage MediaWiki

En plus de traiter> 27, supprimez autant que possible les balises MediaWiki des valeurs de modèle et formatez les informations de base sur le pays.

<détails>

Réponse </ summary>

028.py


import pandas as pd
import re

p_quote = re.compile("'+")
p_br = re.compile("<br/>")
p_ref = re.compile("\<ref\>.*\</ref\>", re.DOTALL)
p_emphasis1 = re.compile("\[\[[^\]]*\|([^\|]*?)\]\]")
p_emphasis2 = re.compile("\[\[(.+?)\]\]")
p_templete1 = re.compile("\{\{\d\}\}")
p_templete2 = re.compile("\{\{.*\|([^\|]*?)\}\}")
p_refname = re.compile("<refname.*")


def remove_markup(a: list):
    ans = {}
    for i in a:
        i = p_quote.sub("", i)
        i = p_br.sub("", i)
        i = p_emphasis1.sub(r"\1", i)
        if p_emphasis2.search(i):
            i = i.replace("[", "").replace("]", "")
        i = p_templete1.sub("", i)
        i = p_templete2.sub(r"\1", i)
        i = p_refname.sub("", i)
        i = re.sub("((emblème national))", r"\1", i)
        i = re.sub("\}\}Fichier.*", "", i).split("=")
        ans[i[0]] = i[1]
    return ans


df = pd.read_json("jawiki-country.json.gz", lines=True)
article = df.query("title == 'Angleterre'")["text"].values[0]
str = re.findall("(?<=Informations de base Pays\n\|).*(?=\n\}\})", article, flags=re.DOTALL)
list = [p_ref.sub("", item) for item in str[0].replace(" ", "").split("\n|")]
print(remove_markup(list))

# -> ...'Slogan': 'Dieuetmondroit (français:Dieu et mes droits)'...
Commentaires

J'ai essayé de supprimer le balisage à une extrémité. Mais cette façon d'écrire ne semble pas bien s'appliquer aux articles en dehors du Royaume-Uni. (Par exemple, dans l'article de Singapour, les paramètres de la largeur du drapeau, etc. n'ont pas pu être extraits.)

No.29 Obtenez l'URL de l'image du drapeau

Utilisez le contenu du modèle pour obtenir l'URL de l'image du drapeau. (Astuce: appelez imageinfo dans l'API MediaWiki pour convertir les références de fichiers en URL)

<détails>

Réponse </ summary>

029.py


import requests
import pandas as pd
import re

p_quote = re.compile("'+")
p_br = re.compile("<br />")
p_ref = re.compile("\<ref\>.*\</ref\>", re.DOTALL)
p_emphasis1 = re.compile("\[\[[^\]]*\|([^\|]*?)\]\]")
p_emphasis2 = re.compile("\[\[(.+?)\]\]")
p_templete1 = re.compile("\{\{\d\}\}")
p_templete2 = re.compile("\{\{.*\|([^\|]*?)\}\}")
p_refname = re.compile("<ref name.*")


def remove_markup(a: list):
    ans = {}
    for i in a:
        i = p_quote.sub("", i)
        i = p_br.sub("", i)
        i = p_emphasis1.sub(r"\1", i)
        if p_emphasis2.search(i):
            i = i.replace("[", "").replace("]", "")
        i = p_templete1.sub("", i)
        i = p_templete2.sub(r"\1", i)
        i = p_refname.sub("", i)
        i = re.sub("((emblème national))", r"\1", i)
        i = re.sub("\}\}Fichier.*", "", i).split("=")
        i[0] = re.sub("^\s", "", i[0])
        i[0] = re.sub("\s$", "", i[0])
        i[1] = re.sub("^\s", "", i[1])
        i[1] = re.sub("\s$", "", i[1])
        ans[i[0]] = i[1]
    return ans


df = pd.read_json("jawiki-country.json.gz", lines=True)
article = df.query("title == 'Angleterre'")["text"].values[0]
str = re.findall("(?<=Informations de base Pays\n\|).*(?=\n\}\})", article, flags=re.DOTALL)
list = [p_ref.sub("", item) for item in str[0].split("\n|")]
page = remove_markup(list)

print(page["Image du drapeau"])
url = 'https://en.wikipedia.org/w/api.php'
PARAMS = {
    "action": "query",
    "format": "json",
    "prop": "imageinfo",
    "iiprop": "url",
    "titles": "File:" + page["Image du drapeau"]
}
response = requests.get(url, params=PARAMS)
data = response.json()
for k, v in data["query"]["pages"].items():
    print(f"{v['imageinfo'][0]['url']}")

# -> https://upload.wikimedia.org/wikipedia/en/a/ae/Flag_of_the_United_Kingdom.svg
Commentaires

En fait, je voulais faire du n ° 28 jusqu'à ʻimport`, mais j'ai un peu changé la partie de la suppression du balisage, donc j'ai posté toutes les lignes.

J'envoie une requête GET en utilisant le module request. Imageinfo of MediaWiki API a été très utile.

Recommended Posts