Skip to content

Instantly share code, notes, and snippets.

@ettorerizza
Created October 6, 2019 12:24
Show Gist options
  • Save ettorerizza/2810b9a5b876c6abd18b86d3481f33f5 to your computer and use it in GitHub Desktop.
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
#!/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