Je résous 100 coups sur le traitement du langage lors d'une session d'étude centrée sur les membres de l'entreprise, mais le code de réponse et la solution Ceci est un résumé des astuces que j'ai trouvées utiles dans le processus. La plupart du contenu a été étudié et vérifié par moi-même, mais il contient également des informations partagées par d'autres membres du groupe d'étude.
Cette fois, c'est une expression régulière, mais il y a eu une réponse du contenu de base aux problèmes difficiles et difficiles.
Je n'ai pas eu l'occasion d'apprendre les expressions régulières sérieusement jusqu'à présent, j'ai donc examiné les connaissances de base à l'avance, mais Document Python original /re.html) et les pages WWW Creators sont faciles à lire et à organiser, ce qui m'a aidé. Certains des documents de type tutoriel ont été écrits par le maître Ruby Mr. Ito, ce qui peut être utile lorsque vous êtes bloqué.
Mettez jawiki-country.json.gz
dans le même répertoire que le fichier ipynb (ou Python)
!gzip -d jawiki-country.json.gz
Ensuite, vous pouvez décompresser le zip.
import json
def load_uk():
with open('jawiki-country.json') as file:
for item in file:
d = json.loads(item)
if d['title'] == 'Angleterre':
return d['text']
print(load_uk())
résultat
{{redirect|UK}}
{{Informations de base Pays
|Nom abrégé=Angleterre
|Nom du pays japonais=Royaume-Uni de Grande-Bretagne et d'Irlande du Nord
|Nom officiel du pays= {{lang|en|United Kingdom of Great Britain and Northern Ireland}}<ref>Nom officiel du pays autre que l'anglais:<br/>
...
import re
def extract_categ_lines():
return re.findall(r'.*Category.*', load_uk())
print(*extract_categ_lines())
résultat
[[Category:Angleterre|*]] [[Category:Royaume du Royaume-Uni|*]] [[Category:Pays membres du G8]] [[Category:Pays membres de l'Union européenne]] [[Category:Nation marine]] [[Category:Pays souverain]] [[Category:Pays insulaire|Kureito Furiten]] [[Category:État / région créé en 1801]]
Puisque l'énoncé du problème contient le mot "extraire les lignes", j'ai envie d'utiliser split ()
pour séparer la valeur de retour de load_uk ()
pour chaque ligne, mais un tel traitement est essentiel. N'est pas. .
Représente" n'importe quel caractère sauf les sauts de ligne ", donc si vous écrivez comme ci-dessus, vous ne pouvez récupérer que la ligne contenant la chaîne de caractères Category
.
def extract_categs():
return re.findall(r'.*Category:(.*?)\]', load_uk())
print(*extract_categs())
résultat
Angleterre|*Royaume du Royaume-Uni|*Pays membres du G8 Pays membres de l'Union européenne Pays marins Pays souverains Pays insulaires|État / région de Kureito Furiten fondé en 1801
Entourez ()
pour capturer la chaîne immédiatement après Category:
. Cependant, j'ai ajouté ?
Après *
pour le rendre non gourmand (spécifiez la correspondance la plus courte) afin que le ]
après ne soit pas pris ensemble.
def extract_sects():
tuples = re.findall(r'(={2,})\s*([^\s=]*).*', load_uk())
sects = []
for t in tuples:
if t[0] == '==':
sects.append([t[1], 1])
elif t[0] == '===':
sects.append([t[1], 2])
elif t[0] == '====':
sects.append([t[1], 3])
return sects
print(*extract_sects())
résultat
['Nom du pays', 1] ['histoire', 1] ['La géographie', 1] ['climat', 2] ['Politique', 1] ['Diplomatie et militaire', 1] ['Division de l'administration locale', 1] ['Grandes villes', 2] ['Science et technologie', 1] ['Économie', 1] ['Exploitation minière', 2] ['Agriculture', 2] ['Commerce', 2] ['devise', 2] ['Compagnie', 2] ['trafic', 1] ['route', 2] ['Chemin de fer', 2] ['livraison', 2] ['Aviation', 2] ['la communication', 1] ['Gens', 1] ['Langue', 2] ['religion', 2] ['mariage', 2] ['éducation', 2] ['culture', 1] ['食culture', 2] ['Littérature', 2] ['philosophie', 2] ['musiques', 2] ['イギリスのポピュラーmusiques', 3] ['films', 2] ['la comédie', 2] ['fleur nationale', 2] ['héritage du monde', 2] ['Vacances', 2] ['Des sports', 1] ['Football', 2] ['Course de chevaux', 2] ['モーターDes sports', 2] ['note de bas de page', 1] ['Article connexe', 1] ['Lien externe', 1]
Puisque ^ \ s =
signifie "tout caractère qui n'est ni vide ni =
",[^ \ s =] +
signifie" un ou plusieurs caractères arbitraires qui ne sont ni vides ni=
". Cela signifie «choses». Il s'agit du nom de la section, qui est la première valeur que vous souhaitez obtenir cette fois. En plus de cela, si vous placez = {2,}
dans ()
, vous pouvez obtenir "deux ou plus` = ʻen ligne".
Pour chaque correspondance, un taple contenant les deux valeurs ci-dessus est retourné, donc je l'ai utilisé pour créer la valeur de retour avec l'instruction for
. Je n'ai pas à m'inquiéter du format de la valeur de retour car il n'est pas spécifié, mais je l'ai choisi comme un tableau de tableaux.
En passant, dans le code ci-dessus, nous préparons d'abord une liste appelée sects
, y mettons des éléments, puis la retournons à la fin, mais l'utilisation de yield
rend cela un peu plus concis. Peut être écrit.
def extract_sects_2():
tuples = re.findall(r'(={2,})\s*([^\s=]+).*', load_uk())
for t in tuples:
if t[0] == '==':
yield [t[1], 1]
elif t[0] == '===':
yield [t[1], 2]
elif t[0] == '====':
yield [t[1], 3]
print(*extract_sects_2())
Une fonction utilisant yield
est appelée un générateur et renvoie un itérateur (itérateur du générateur) (pour plus de détails, voir documentation Python. Voir # term-generator)), il semble que l'itérateur puisse être développé avec *
devant lui comme ci-dessus, ou converti en liste en le passant à list ()
.
def extract_media_files():
return re.findall(r'(?:File|Fichier):(.+?)\|', load_uk())
extract_media_files()
résultat
['Royal Coat of Arms of the United Kingdom.svg',
'Battle of Waterloo 1815.PNG',
'The British Empire.png',
'Uk topo en.jpg',
'BenNevis2005.jpg',
...
Je dois utiliser ()
pour représenter " File
ou file
", mais je ne veux pas capturer cela, alors j'ai écrit ?:
Immédiatement après (
? ".
Au fait, la raison pour laquelle print ()
n'est pas utilisé dans la dernière ligne est que si vous renvoyez une liste etc. ici, Jupyter la formatera puis la sortira.
def extract_template():
data = re.search(r'\{\{Informations de base.*\n\}\}', load_uk(), re.DOTALL).group()
tuples = re.findall(r'\n\|(.+?)\s=\s(.+?)(?:(?=\n\|)|(?=\}\}\n))', data, re.DOTALL)
return dict(tuples)
extract_template()
résultat
{'Nom abrégé': 'Angleterre',
'Nom du pays japonais': 'Royaume-Uni de Grande-Bretagne et d'Irlande du Nord',
'Nom officiel du pays': '{{lang|en|United Kingdom of Great Britain and Northern Ireland}}<ref>Nom officiel du pays autre que l'anglais:<br/>\n*{{lang|gd|An Rìoghachd Aonaichte na Breatainn Mhòr agus Eirinn mu Thuath}}([[Gaélique écossais]])<br/>\n*{{lang|cy|Teyrnas Gyfunol Prydain Fawr a Gogledd Iwerddon}}([[Pays de Galles]])<br/>\n*{{lang|ga|Ríocht Aontaithe na Breataine Móire agus Tuaisceart na hÉireann}}([[irlandais]])<br/>\n*{{lang|kw|An Rywvaneth Unys a Vreten Veur hag Iwerdhon Glédh}}([[Cornouailles]])<br/>\n*{{lang|sco|Unitit Kinrick o Great Breetain an Northren Ireland}}([[Écossais]])<br/>\n**{{lang|sco|Claught Kängrick o Docht Brätain an Norlin Airlann}}、{{lang|sco|Unitet Kängdom o Great Brittain an Norlin Airlann}}(アルスター・Écossais)</ref>',
...
'Numéro de téléphone international': '44'}
Personnellement, c'était la question la plus difficile de ce chapitre. Cependant, j'ai appris le processus des difficultés, donc j'écrirai un peu plus sur le cœur du problème, re.findall ()
. Lorsque vous réfléchissez au type d'expression régulière à utiliser ici, probablement au début
re.findall(r'\n\|(.+)\s=\s(.+)\n\|', data)
Je pense qu'un code comme celui-ci me vient à l'esprit. Cependant, lorsque j'essaie de faire cela, je peux voir que la partie que je voulais prendre de manière égale, comme le nom du pays japonais '':
la Grande-Bretagne et le Royaume-Uni d'Irlande du Nord '', n'est pas prise. La cause de ceci est
\n|Nom abrégé=Angleterre\n|Nom du pays japonais
Quand il y a une chaîne de caractères comme, si c'est l'expression régulière ci-dessus\n|Nom abrégé=Angleterre\n|
Après un match, commencez à chercher le prochain matchjournée
C'est parce qu'il devient la chaîne de caractères aprèsdocumentSivousutilisezl'expressionci-dessus,l'expressionrégulièreci-dessusestjournée
Devantde\n|
Nefonctionnepascaril"consomme").
Alors que faire\n|
Il existe une méthode appelée "look-ahead" pour éviter la consommation de. En tant que code, l'expression régulière\n\|
À(?=)
Insérez-le et procédez comme suit.
re.findall(r'\n\|(.+)\s=\s(.+)(?=\n\|)', load_uk())
Si vous l'exécutez à nouveau avec ceci, vous devriez être en mesure d'obtenir correctement les lignes telles que «nom du pays japonais». Cependant, si vous regardez attentivement la chaîne de caractères obtenue ici, seule la première ligne expliquant le nom officiel du pays est incluse. Cela signifie que le . +
Écrit dans le second ()
correspondra à "un ou plusieurs caractères arbitraires sauf le saut de ligne ( \ n
). " En d'autres termes, il n'est pas possible de franchir les lignes.
Par conséquent, passez un module appelé re.DOTALL
à findall ()
. Ensuite, . +
Va chercher "un ou plusieurs caractères arbitraires", mais si vous laissez +
gourmand, vous en aurez trop. Ajoutons un «?» À la fin.
re.findall(r'\n\|(.+?)\s=\s(.+?)(?=\n\|)', load_uk(), re.DOTALL)
Je pense que c'est à peu près OK, mais si vous regardez de près les résultats renvoyés, il y a un problème que vous obtenez trop à la fin. Par conséquent, regardez en avant la chaîne de caractères après le modèle et modifiez-la comme suit afin qu'elle corresponde même si c'est }} \ n
.
re.findall(r'\n\|(.+?)\s=\s(.+?)(?:(?=\n\|)|(?=\}\}\n))', data, re.DOTALL)
Avec cela, j'ai finalement écrit le code qui satisfait la spécification de l'énoncé du problème, mais si je sens que j'ai emballé trop de choses dans une ligne, je peux utiliser re.complile ()
pour séparer les lignes comme suit. pense.
pattern = re.compile(r'\n\|(.+?)\s=\s(.+?)(?:(?=\n\|)|(?=\}\}\n))', re.DOTALL)
tuples = pattern.findall(data)
Si vous souhaitez insérer un saut de ligne dans la partie expression régulière, vous pouvez ajouter + re.MULTILINE
après re.DOTALL
.
def remove_emphases():
d = extract_template()
return {key: re.sub(r'\'{2,5}', '', val) for key, val in d.items()}
remove_emphases()
résultat
{'Nom abrégé': 'Angleterre',
'Nom du pays japonais': 'Royaume-Uni de Grande-Bretagne et d'Irlande du Nord',
'Nom officiel du pays': '{{lang|en|United Kingdom of Great Britain and Northern Ireland}}<ref>Nom officiel du pays autre que l'anglais:<br/>\n*{{lang|gd|An Rìoghachd Aonaichte na Breatainn Mhòr agus Eirinn mu Thuath}}([[Gaélique écossais]])<br/>\n*{{lang|cy|Teyrnas Gyfunol Prydain Fawr a Gogledd Iwerddon}}([[Pays de Galles]])<br/>\n*{{lang|ga|Ríocht Aontaithe na Breataine Móire agus Tuaisceart na hÉireann}}([[irlandais]])<br/>\n*{{lang|kw|An Rywvaneth Unys a Vreten Veur hag Iwerdhon Glédh}}([[Cornouailles]])<br/>\n*{{lang|sco|Unitit Kinrick o Great Breetain an Northren Ireland}}([[Écossais]])<br/>\n**{{lang|sco|Claught Kängrick o Docht Brätain an Norlin Airlann}}、{{lang|sco|Unitet Kängdom o Great Brittain an Norlin Airlann}}(アルスター・Écossais)</ref>',
...
'Forme établie 4': 'Changement du nom de pays actuel "Grande-Bretagne et Royaume-Uni d'Irlande du Nord"',
...
Par rapport à 25, les expressions régulières sont un problème qui peut être résolu avec seulement des connaissances de base, mais il y a une mise en garde que si vous mettez un espace après «2», cela ne fonctionnera pas dans certains cas.
Je pense que la notation interne du dictionnaire est une notation propre à Python, mais au fur et à mesure que je m'y habitue, je peux l'écrire de manière concise, donc je l'utilise souvent personnellement.
def remove_links():
d = remove_emphases()
return {key: re.sub(r'\[\[.*?\|?(.+?)\]\]', r'\\1', val) for key, val in d.items()}
remove_links()
résultat
{'Nom abrégé': 'Angleterre',
'Nom du pays japonais': 'Royaume-Uni de Grande-Bretagne et d'Irlande du Nord',
'Nom officiel du pays': '{{lang|en|United Kingdom of Great Britain and Northern Ireland}}<ref>Nom officiel du pays autre que l'anglais:<br/>\n*{{lang|gd|An Rìoghachd Aonaichte na Breatainn Mhòr agus Eirinn mu Thuath}}(Gaélique écossais)<br/>\n*{{lang|cy|Teyrnas Gyfunol Prydain Fawr a Gogledd Iwerddon}}(Pays de Galles)<br/>\n*{{lang|ga|Ríocht Aontaithe na Breataine Móire agus Tuaisceart na hÉireann}}(Irlandais)<br/>\n*{{lang|kw|An Rywvaneth Unys a Vreten Veur hag Iwerdhon Glédh}}(Cornouailles)<br/>\n*{{lang|sco|Unitit Kinrick o Great Breetain an Northren Ireland}}(Écossais)<br/>\n**{{lang|sco|Claught Kängrick o Docht Brätain an Norlin Airlann}}、{{lang|sco|Unitet Kängdom o Great Brittain an Norlin Airlann}}(Ulster écossais)</ref>',
'Image du drapeau': 'Flag of the United Kingdom.svg',
'Image de l'emblème national': 'Fichier:Royal Coat of Arms of the United Kingdom.svg|85px|Emblème national britannique',
...
Que veux-tu faire[[]]
S'il y a une partie entourée par, retirez le contenu. Cependant, en elle|
S'il y a|
J'ai essayé de le résoudre en définissant «ne retirer que l'arrière de».|
Je ne sais pas si ça va sortir ou pas, donc derrière?
Est ajouté pour spécifier qu'il correspond à 0 ou 1 répétition.
def remove_markups():
d = remove_links()
#Supprimer les liens externes
d = {key: re.sub(r'\[http:.+?\s(.+?)\]', '\\1', val) for key, val in d.items()}
#Supprimer ref (balise de début et balise de fin ensemble) et br
d = {key: re.sub(r'</?(ref|br).*?>', '', val) for key, val in d.items()}
return d
remove_markups()
résultat
{'Nom abrégé': 'Angleterre',
'Nom du pays japonais': 'Royaume-Uni de Grande-Bretagne et d'Irlande du Nord',
'Nom officiel du pays': '{{lang|en|United Kingdom of Great Britain and Northern Ireland}}Nom officiel du pays autre que l'anglais:\n*{{lang|gd|An Rìoghachd Aonaichte na Breatainn Mhòr agus Eirinn mu Thuath}}(Gaélique écossais)\n*{{lang|cy|Teyrnas Gyfunol Prydain Fawr a Gogledd Iwerddon}}(Pays de Galles)\n*{{lang|ga|Ríocht Aontaithe na Breataine Móire agus Tuaisceart na hÉireann}}(Irlandais)\n*{{lang|kw|An Rywvaneth Unys a Vreten Veur hag Iwerdhon Glédh}}(Cornouailles)\n*{{lang|sco|Unitit Kinrick o Great Breetain an Northren Ireland}}(Écossais)\n**{{lang|sco|Claught Kängrick o Docht Brätain an Norlin Airlann}}、{{lang|sco|Unitet Kängdom o Great Brittain an Norlin Airlann}}(Ulster écossais)',
'Image du drapeau': 'Flag of the United Kingdom.svg',
...
'Valeur de la population': '63,181,775United Nations Department of Economic and Social Affairs>Population Division>Data>Population>Total Population',
...
{{lang|.+?|.+?}}
Je pensais que de tels modèles devraient être supprimés,~~je suis fatigué~~Il ne figurait pas dans le tableau de référence rapide, je l'ai donc laissé tel quel cette fois.
import requests
import json
def get_flag_url():
d = remove_markup()['Image du drapeau']
url = 'https://www.mediawiki.org/w/api.php'
params = {'action': 'query',
'titles': f'File:{d}',
'format': 'json',
'prop': 'imageinfo',
'iiprop': 'url'}
res = requests.get(url, params)
return res.json()['query']['pages']['-1']['imageinfo'][0]['url']
get_flag_url()
résultat
'https://upload.wikimedia.org/wikipedia/commons/a/ae/Flag_of_the_United_Kingdom.svg'
Un problème qui ne demande soudainement de connaître HTTP qu'à la fin. C'est un peu difficile à résoudre sans connaître la demande et la réponse. Si vous ne comprenez pas bien et que vous voulez le comprendre grossièrement, vous pouvez utiliser la vidéo ici, et si vous voulez en savoir un peu plus, [Document MDN](https: //) developer.mozilla.org/en/docs/Web/HTTP/Overview) peut être utile.
Dans ce problème, vous pouvez extraire l'URL de l'image du drapeau de la réponse renvoyée lorsque vous envoyez une requête GET à l'API MediaWiki avec Python, etc., mais pour cela, vous devez importer un module spécial.
Il semble que vous puissiez utiliser urllib.request si vous ne voulez pas vous soucier d'installer des packages externes, mais j'ai décidé d'utiliser des requêtes car je l'avais installé dans le passé. C'est un code plus simple, et je l'ai écrit parce qu'il est largement utilisé, y compris l'exemple sur la page ici de MediaWiki. Je pense que c'est facile.
À propos, les 7 lignes du milieu peuvent être écrites sur 2 lignes comme indiqué ci-dessous, mais dans ce cas, l'URL s'agrandira trop horizontalement, il est donc préférable de séparer les lignes comme décrit ci-dessus.
url = f'https://www.mediawiki.org/w/api.php?action=query&titles=File:{d}&format=json&prop=imageinfo&iiprop=url'
res = requests.get(url)
Les expressions régulières sont un outil qui est utilisé non seulement dans le traitement du langage mais aussi dans le développement Web, mais ce chapitre couvre un large éventail de sujets et j'ai senti que c'était un bon matériel pédagogique.
Comme mentionné ci-dessus, je l'ai écrit dans le but de créer un code précis et concis, mais si vous avez des erreurs, veuillez commenter.
Recommended Posts