Created
October 6, 2019 12:24
-
-
Save ettorerizza/2810b9a5b876c6abd18b86d3481f33f5 to your computer and use it in GitHub Desktop.
Script destiné à scraper les noms de cabinettards sur un vieux site au HTML très pourri
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/usr/bin/env python | |
#-*- coding: utf-8 -*- | |
""" | |
Script destiné à scraper les noms de cabinettards sur le vieux site au HTML très pourri de 4instance | |
""" | |
# J'importe les modules externes qui seront nécessaires | |
# A installer au préalable en ligne de commandes (ou dans le terminal de VSCode) | |
# exemple : pip install bs4 ; pip install requests ; pip install pandas ; pip install regex | |
# Module pour les expressions régulières meilleur que celui par défaut pour traiter les lettres accentuées, à installer. | |
import regex as re | |
import requests # Pour se rendre sur une page plus facilement. A installer. | |
# Pour récupérer des éléments dans une page web. A installer | |
from bs4 import BeautifulSoup | |
import pandas as pd # Pour travailler avec des tableaux de données. A installer | |
# Sera utile par la suite | |
def deduplicate(seq): | |
""" | |
Petite fonction pour effacer les doublons d'une liste en préservant l'ordre originel | |
""" | |
seen = set() | |
seen_add = seen.add | |
return [x for x in seq if not (x in seen or seen_add(x))] | |
##################################################################### | |
# PARTIE 1 : récupérer les liens vers les pages web de chaque ministre | |
##################################################################### | |
# URL de départ contenant les liens vers les infos qui nous intéressent | |
start_page = "http://www.4instance.mobi/HTML_Kabinettengids_GuideDesCabinets/GouvernementFederal/GF.html" | |
# Je me rends sur cette page à l'aide du module requests, et je stocke le résultat dans une variable r | |
r = requests.get(start_page) | |
# Affiche le code source de la page web en question (c'est juste une bouillie de HTML) | |
# print(r.content) | |
# Je crée un objet BeautifulSoup, qui correspond au HTML parsé | |
soup = BeautifulSoup(r.content, "html.parser") | |
# J'utilise un sélecteur CSS pour extraire les éléments HTML contenant les liens qui nous intéressent | |
# J'extrait les liens des éléments html et je ne gard que ceux qui contiennent le mot "GouvernementFederal" | |
# J'ajoute ces liens dans une liste vide créée au préalable | |
liste_de_liens = [] | |
for link in soup.find_all('a', attrs={'href': re.compile("GouvernementFederal")}): | |
liste_de_liens.append(link.get('href')) | |
# On voit que les liens sont relatifs. | |
# print(liste_de_liens) | |
# Nous allons leur ajouter l'URL de base du site, afin qu'ils deviennent des liens absolus | |
# ceci s'appelle une "compréhension de liste". C'est équivalent à une boucle for, mais s'écrit de manière plus condensée | |
liens_finaux = deduplicate( | |
["http://www.4instance.mobi" + lien for lien in liste_de_liens]) | |
# print(liens_finaux) | |
################################################ | |
# PARTIE 2 : récupérer les infos dans chaque page | |
################################################ | |
# La procédure sera similaire à celle de la partie 1 | |
# Mais je vais cette fois créer une fonction qui | |
# récupère les infos dans une page web, puis appliquer cette fonction à tous les liesn de la liste avec | |
# # une boucle for. Cette méthode est plus propre. | |
def recupere_noms(url): | |
""" | |
Cette fonction prend en entrée une URL et renvoie une liste contenant | |
les noms de personnes mentionnés dans la page web en question. | |
Elle utilise d'abord Beautiful Soup pour sélectionner le bloc HTML où se trouvent | |
les noms, puis une regex pour les extraires et les nettoyer. | |
""" | |
r = requests.get(url) | |
liste_elements = [] | |
soup = BeautifulSoup(r.content, "html.parser") | |
html_element = soup.select("tr > td") | |
for el in html_element: | |
liste_elements.append(el.get_text("\n", strip=False)) | |
text = " ".join(liste_elements) | |
# Peut récupérer un nom de famille composé de quatre éléments séparés max | |
regex = r"""\b[[:upper:]][[:lower:]]+['\- ]?([[:upper:]][[:lower:]]+)?(van|de|den|d'|[[:upper:]]+)\s?(van|de|den|d'|[[:upper:]]+)?\s?(van|de|den|d'|[[:upper:]]+)?\s?([[:upper:]]+)?\b""" | |
test = re.finditer(regex, text, re.MULTILINE | re.VERBOSE) | |
return [x.group().strip() for x in test] | |
# On teste la fonction sur une URL, par exemple celle de Vanackere | |
print("resultats: ", recupere_noms( | |
"http://www.4instance.mobi/HTML_Kabinettengids_GuideDesCabinets/GouvernementFederal/YvesLeterme_FR.html")) | |
# On applique la fonction à toutes les URLs à l'aide d'une boucle | |
# et on écrit le résultat dans un fichier CSV, que l'on nettoyera ensuite manuellement | |
""" | |
list_of_lists = [] | |
for url in liens_finaux: | |
list_of_lists.append(pd.DataFrame(deduplicate(recupere_noms(url)))) | |
df = pd.concat(list_of_lists, axis=1) | |
# Ecrit le résultat dans un fichier CSV | |
df.to_csv("liste_cabinettards.csv", sep='\t', encoding='utf-8', header=None) | |
""" |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment