Comment scraper les profils des Chief Happiness Officer de Paris sur Linkedin avec Python et Selenium

Les Chief Happiness Officer, ou les M. et Mme. Bonheur du bureau, fleurissent dans le monde. Et pour cause : d’après le Huffington Post, dans un article publié le 22/03/2014, il existe une nette corrélation entre l’épanouissement affectif éprouvé au bureau, et la productivité au travail. M. Bonheur au service de M. Performance, voilà la belle affaire.
Nous allons aujourd’hui voir comment récupérer les coordonnées de ces professionnels sur le réseau social linkedin.com, à Paris, sur la première page, avant de l’enregistrer dans un fichier csv.
Quelle donnée allons nous extraire ?
Vous trouverez ci-dessous la liste des champs que nous allons extraire :
- Nom
- Position
- Région
- URL
Et maintenant, un screenshot afin de visualiser la présence de chaque élément dans le site web :
Trouvez la donnée
Avant de commencer à construire le scraper, nous devons trouver où les données sont présentes dans les balises HTML de la page Web. Il faut connaître le fonctionnement des balises HTML de la page pour pouvoir faire ça.
Nous allons supposer que vous avez déjà des bases en HTML et que vous connaissez le langage Python. Vous n’avez pas besoin de plus de connaissances pour réaliser ce tutoriel.
Si vous ne connaissez ni le HTML, ni le CSS, ni le Python, prenez le temps de lire Premiers pas avec HTML – Mozilla Developer Network, Tutoriel CSS W3 School, et https://www.programiz.com/python-programming
Nous allons inspecter le code HTML de la page Web et localiser les données, en suivant la logique suivante :
- Inspecter l’élément
- Trouver la balise correspondante
Inspecter l’HTML
Ouvrez votre navigateur Chrome, et rendez-vous sur le site de Linkedin : https://www.linkedin.com. Vous pouvez le faire avec d’autres navigateurs, mais ce tutoriel se fait sur Chrome, et facilitera votre apprentissage.
Afin de rentrer sur le réseau social et d’en saisir les données, rentrez vos identifiants, et connectez vous.
Une fois sur le site, taper le mot clé souhaité, ici : chief happiness officer. Appuyez ensuite sur la touche Entrée de votre clavier.
Faites, un clique droit, puis cliquer sur Inspecter.
Nous allons maintenant chercher le tag CSS de chaque élément, avant de lancer notre scraper. Pour faciliter la recherche, cliquer sur le curseur en bas à gauche. Passez ensuite votre souris sur les éléments que nous avons cités en introduction.
En passant légèrement votre souris sur chacun des éléments évoqués en introduction, vous retrouverez les classes suivantes associées :
- Nom : span.name.actor-name
- Position : p.subline-level-1
- Région : p.subline-level-2
- Image : image.image-lazy.loaded
- URL : a.search-resul_result-link
Comment configurer son ordinateur pour le Web Scraping
Nous allons utiliser Python 3 pour ce tutoriel. Pour commencer, vous avez besoin d’un ordinateur avec Python 3 et PIP installé dedans.
La plupart des systèmes d’exploitation UNIX comme Linux et Mac OS sont livrés avec Python déjà installé. Mais, tous les systèmes d’exploitation Linux ne sont pas livrés avec Python 3 par défaut.
Vérifions votre version de python. Ouvrez un terminal (sous Linux et Mac OS) ou Invite de commandes (sous Windows) et tapez
1 |
python --version |
Si vous n’avez pas Python 3, il va falloir l’installer.
Installer Python et Selenium
Pour installer Python et PIP, vous pouvez vous rendre sur le post que nous avons déjà fait à ce sujet : https://lobstr.io/index.php/2018/02/15/installer-librairies-python-mac-os/
Pour installer Selenium, il suffit d’ouvrir votre commande, et de
1 |
pip install selenium |
Pour plus de renseignements sur Selenium et ses fonctionnalités avec Python, leur documentation est fournie et très utile : http://selenium-python.readthedocs.io/index.html
Le code
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 |
# python package import csv import time import random import sys import os # selenium package from selenium import webdriver from selenium.webdriver.common.keys import Keys from selenium.webdriver.common.desired_capabilities import DesiredCapabilities from selenium.webdriver.chrome.options import Options from selenium.webdriver.support.ui import WebDriverWait from selenium.webdriver.support import expected_conditions as EC from selenium.webdriver.common.by import By from selenium.common.exceptions import NoSuchElementException from selenium.common.exceptions import TimeoutException from selenium.common.exceptions import UnexpectedAlertPresentException from selenium.common.exceptions import WebDriverException from selenium.common.exceptions import StaleElementReferenceException # identifiants email_address = "your@mail.com" password = "your_password" search_item = "Chief Happiness Officer" # fonction pause def pause(): time_break = random.randint(5,10) # print "Pause de " + str(time_break) + " seconde(s)." return time.sleep(time_break) # options options = webdriver.ChromeOptions() options.add_argument("--kiosk") capa = DesiredCapabilities.CHROME capa["pageLoadStrategy"] = "none" driver = webdriver.Chrome(desired_capabilities=capa, chrome_options=options) wait = WebDriverWait(driver, 30) pause() print "Driver 1 ouvert" # url de depart linkedin_url = "https://www.linkedin.com/" # aller sur linkedin driver.get(linkedin_url) #1 : page principale try: wait.until(EC.presence_of_element_located( (By.ID, "login-submit")) ) except (TimeoutException): sys.exit("Error message - loading page") pause() print "Connecte a Linkedin - 1" # s'identifier driver.find_element_by_id("login-email").send_keys(email_address) pause() driver.find_element_by_id("login-password").send_keys(password) pause() driver.find_element_by_id("login-submit").click() pause() wait.until(EC.element_to_be_clickable( (By.ID, "nav-typeahead-wormhole")) ) pause() print "Profil connecte a Linkedin - 1" # lancer la recherche driver.find_element_by_css_selector("div.nav-search-typeahead input").send_keys(search_item) pause() driver.find_element_by_css_selector("div.nav-search-typeahead input").send_keys(Keys.ENTER) wait.until(EC.presence_of_element_located( (By.CSS_SELECTOR, "span.name.actor-name")) ) wait.until(EC.presence_of_element_located( (By.CSS_SELECTOR, "h3.search-results__total") )) pause() print "Fin de la recherche avec mot cle : " + search_item # scroll down smoothly scheight = .1 while scheight < 1.0: driver.execute_script("window.scrollTo(0, document.body.scrollHeight*%s);" % scheight) scheight += .1 pause() wait.until(EC.element_to_be_clickable( (By.CSS_SELECTOR, 'div.next-text') )) try: print driver.find_element_by_css_selector('div.next-text').text except(NoSuchElementException): print 'No div.next-text' finally: pass # ouvrir csv with open('linkedin_items.csv', 'w') as csvfile: cwriter = csv.writer(csvfile, delimiter=' ', quotechar='$', quoting=csv.QUOTE_MINIMAL) # prendre infos profils = driver.find_elements_by_css_selector("div.search-result__wrapper") # boucle for profil in profils: # creer tableau csv_row = [] # name try: name_location = profil.find_element_by_css_selector( "span.name.actor-name") driver.execute_script( "arguments[0].scrollIntoView({behavior: 'smooth', block: 'center', inline: 'nearest'});", name_location) name = name_location.text.encode('utf-8') csv_row.append(name) except (NoSuchElementException, WebDriverException, StaleElementReferenceException): name = '' csv_row.append(name) finally: pass if name is not 'None': # url try: url_profil = profil.find_element_by_css_selector("a.search-result__result-link").get_attribute('href') csv_row.append(url_profil) except (NoSuchElementException, WebDriverException, StaleElementReferenceException): url_profil = 'None' csv_row.append(url_profil) finally: pass # position try: position = profil.find_element_by_css_selector("p.subline-level-1").text.encode('utf-8') csv_row.append(position) except (NoSuchElementException, WebDriverException, StaleElementReferenceException): position = 'None' csv_row.append(position) finally: pass # localisation try: localisation = profil.find_element_by_css_selector("p.subline-level-2").text.encode('utf-8') csv_row.append(localisation) except (NoSuchElementException, WebDriverException, StaleElementReferenceException): localisation = 'None' csv_row.append(localisation) finally: pass # copier dans le csv try: cwriter.writerow(csv_row) print("-- SUCCESS : %s" % name) except(NoSuchElementException, WebDriverException, StaleElementReferenceException, UnicodeEncodeError): print("Error message - csv") finally: pass # fermer les navigateurs print("Bravo !") driver.close() |
Pour exécuter le script, ouvrez votre éditeur Sublime Text 3, copier-coller le code ci contre, et enregistrez le sous le nom de linkedin_extract.py. Si vous ne savez pas comment l’installer, rendez-vous ici : https://lobstr.io/index.php/2018/02/08/comment-pourquoi-installer-sublim-text/
Veiller à remplacer les deux variables email_address et password situées en haut du code et d’y ajouter vos identifiants personnels. Vous noterez par ailleurs que nous avons créé une fonction pause( ) afin de récupérer les données de façon automatisée tout en respectant la capacité des serveurs de la société en question.
Dans votre commande, placez ensuite la ligne suivante :
1 |
python linkedin_extract.py |
Un navigateur va directement s’ouvrir, et vous pourrez observer, sous vos yeux ébahis, la collecte de données. En direct.
Vous devriez retrouver dans le même dossier que le dossier où se trouve le script, un fichier .csv, nommé linkedin_items.csv. Une fois ouvert, et formaté sur excel, vous obtiendrez un fichier .xls comme suit :
Vous pouvez également télécharger le code sur notre Github, à l’adresse suivante : https://gist.github.com/Lobstrio/7f68492c218a52231b132216335b83e3. N’hésitez pas à nous indiquer dans les commentaires, ou sur le github, si le script fonctionne bien chez vous aussi.
Limitations connues
Le script permet de collecter les données, et de les enregistrez au format .csv. Toutefois, vous ne pourrez récolter que les données de la première page, tandis que d’autres données (école, nom de société, entre autres) ne seront pas récoltées, ou récoltées de façon partielle. Par ailleurs, si vous réalisez cette collecte de façon trop agressive et à trop grande échelle, il n’est pas impossible que Linkedin bloque votre compte et vous empêche l’accès au site.
Si vous avez besoin d’aide pour scraper des milliers de données de façon récurrente et à grande échelle, vous pouvez nous contacter via le formulaire ci-dessous :
Avertissement: Tout code fourni dans nos tutoriels est destiné à des fins d’illustration et d’apprentissage uniquement. Nous ne sommes pas responsables de la façon dont il est utilisé et n’assumons aucune responsabilité pour toute utilisation préjudiciable du code source. La simple présence de ce code sur notre site n’implique pas que nous encourageons le scraping ou l’extraction de données des sites référencés dans le code et le tutoriel qui l’accompagne. Les tutoriels ne font qu’illustrer la technique de programmation des scrapers web pour les sites internet populaires. Nous ne sommes pas obligés de fournir un support pour le code, cependant, si vous ajoutez vos questions dans la section des commentaires, nous pouvons vous y répondre périodiquement.