Apprendre Python dans une formation présentielle : le niveau supérieur

//Apprendre Python dans une formation présentielle : le niveau supérieur

Après mon précédent article (apprendre un langage de programmation), j’ai continué l’apprentissage du langage Python, cette fois lors d’une formation présentielle de 3 jours étalés sur 3 mois aux Ix-Labs (Peyronnet)

Petit rappel avant de commencer : ou j’en étais avant de démarrer cette formation

J’avais déjà lu 2 ouvrages sur Python (Swinnen + Automate The Boring Stuff) et finalisé la track Python de CodeAcademy. Il y a fort, fort longtemps, j’ai fait un IUT Informatique ou le langage majeur était Java (J2EE).

L’idée ici étant toujours de donner une idée du temps que cela prend d’apprendre le dev et de ce qu’on peut espérer obtenir en terme de compétences.

Formation en ligne VS formation classique : le GAP gigantesque

SPOILER :  si vous pensiez être devenu développeur après avoir bouclé un track sur CodeAcademy ou une autre plateforme du genre, vous êtes très très loin du compte !

Le choix de la formation Python :

Cela faisait un moment que je lorgnais les formations Py en présentiel pour gravir un nouvel échelon de compétences. Après m’être renseigné autour de moi, j’avais retenu Human Coders dans un premier temps avant que, coincidence, Sylvain Peyronnet m’informe que les IX Labs allaient se positionner sur ce créneau car on avait été plusieurs à lui en avoir déjà fait la demande. Je me suis donc retrouvé à Rouen avec 4 compagnons de galère (Cédric Guérin, Julien Deneuville, Sylvain Sengbandith et Maxime Legendre). Outre le fait d’être estampillée Peyronnet et la proximité géographique, le format même de la formation m’a séduit par son originalité : 3 jours de cours en présentiel étalés sur 3 mois avec chaque semaine des exercices à rendre et un projet à présenter à l’arrivée. Bref, de quoi être vraiment motivé, et surtout certain de pratiquer ! La formation s’est achevée en décembre 2017.

Le programme du cursus Python aux Ix-labs :

Beaucoup de chose, en peu de temps !

Jour 1 : Les bases de Python mais pas que !

  • Présentation et Installation de Python

  • Base du langage Python

  • Acquisition des données

  • Connexion aux BDDS MySQL

  • Analyser une page Web

Jour 2 : Manipulation de données et DataViz

  • Représenter ses données avec Matplotlib

  • Numpy et Pandas

  • Python et les Statistiques

  • Le Clustering en Python

  • Les Bandits Manchots

Jour 3 : DataScience et Machine Learning

  • L’apprentissage en Python

  • Les systèmes de recommandation

  • Réalisation d’un Dashboard avec Flask

  • Réaliser un Dashboard avec Google Analytics

  • Python et Elastic Search

  • Pandas : GroupBy, Transform et Apply

Un programme très dense donc, parfois un peu trop pour mes maigres capacités 🙂 L’avantage c’est qu’on est reparti avec les slides et les codes associés. Tout ceci s’est déroulé au format TP, donc avec beaucoup de pratique, pratique renforcée par les devoirs à faire à la maison. Bref, c’est beaucoup de boulot et cela prend un max de temps. Cédric, qui chronomètre son temps passé, est arrivé une semaine à 80 heures de Python !!! Pour ma part, c’était 40 heures minimum.

Ce que je sais faire aujourd’hui avec Python :

Bien plus qu’hier, mais toujours pas autant que je voudrais ! Les bases du langage sont acquises, j’ai une bonne idée du niveau avancé mais cela ne m’est pas encore naturel, loin de là. Je pense avoir par contre développé un bon niveau en scraping / parsing. En effet, en tant que SEO, ce volet de la programmation m’intéressait tout particulièrement (j’avais surtout plein d’idées à mettre en prod). Grâce à la formation ET à l’aide de Bruno Vial (à qui je dois beaucoup de bières et qui touche bien sa mère en Python), j’ai acquis un bon niveau avec Scrapy, BeatutifulSoup, Request et la « Concurency » (multithreading).  Je vais y revenir après. Je me débrouille pas mal avec Pandas, je sais me connecter et écrire dans une BDD avec la lib SQLAlchemy (plus ou moins ^^), je sais calculer le PR interne depuis un export screaming frog, me connecter à diverses APIs…

Scrapy

Mon 1er Projet d’étude : un petit crawler qui donne des KPIs sur les liens issus de la Search Console

C’est parti d’une demande concrète de mon pote Mathieu Janin, qui travaille régulièrement sur des levées de pénalités et qui avait besoin de « quelque chose » qui puisse parcourir une longue liste de liens issus de la Search Console, et sortir quelques KPI (Ancre, DF/NF, Nbre de liens internes, Nbre de liens externes).

J’ai donc profité de ce projet pour inaugurer mon Github (au passage j’ai bien galéré et je n’y comprends toujours pas grand chose…). Ici, je ne vous présente pas un « super code » ou quoi que ce soit, je vous partage, histoire de vous faire une idée, ce que moi j’ai été capable de faire avec la formation que j’ai reçu.

Pour faire mon crawler, j’ai donc utilisé :

  • Request (je voyais pas l’intérêt de faire un Scrapy pour si peu)
  • BeautifulSoup
  • La librairie concurrent.futures (le projet dans le projet, je voulais apprendre le multithreading – j’ai testé avec et sans, le gain de vitesse est immense)

Bref, au préalable il vous faut exporter la liste de vos liens dans la GSC, puis la passer en paramètre, via ligne de commande, au script (mon formateur tenait tout particulièrement à argparse alors j’ai pris le pli ^^). Ca ressemble à ça :

python gsc_links_analyzer.py -d liste_de_lien.csv

Rapidement (normalement) et en sortie, vous aurez un CSV avec les KPIs définies plus haut. Il va de soit que ce petit script peut servir à d’autres choses moyennant des micros modifs :

  • Vérifier une liste de lien issue de n’importe quelle source
  • Monitorer ses liens et vérifier leur présence
  • Horodater l’évolution des KPIs
  • etc etc…

Je mets le code en dessous parce que quand même, ça fait classe !

Mon 2eme projet (toujours pas terminé) et les crawlers que j’ai réalisé pour moi :

J’ai appris (à la dure, et encore une fois grâce à l’aide de Bruno Vial) à utiliser Scrapy. C’est un framework de dingue pour le scraping que j’adore utiliser. Je ne fais d’ailleurs quasiment plus que ça.

Mon premier projet devait fonctionner comme suit :

  1. Grace à une requête (mot clé) passé en paramètre, mon robot récupère dans un premier temps la liste des X (x étant modifiable selon mon humeur) sites présent sur la SERP Google
  2. Un robot dans le robot : Sur la base des X URLs, mon script récupère le contenu nettoyé tout en conservant certaines balises que j’estime pertinente
  3. Un autre script de traitement : Analyse de Corpus a coup de TF/IDF – BM25 et tutti quanti pour générer du contenu auto

Les points 1 et 2 sont fait (et c’est déjà pas mal), je n’ai pas démarré le 3. J’ai cependant en parallèle réalisé un bot qui monitore (toujours avec Scrapy comme socle) les tarifs de mes concurrents. Je suis d’ailleurs actuellement en galère avec la gestion SQL (pour un horodatage plus simple que mon CSV actuel) de ma pipeline Scrapy. J’ai aussi un bot de monitoring pour notre parc de site qui vérifie les changements d’éléments, les codes réponses etc… Bref je scrape.

Les projets de 2 des copains : Un crawler SEO et un réanimateur de site

Comme je ne suis pas une référence, sachez qu’un de mes camarades à fait un crawler SEO qui stocke sa data dans un MongoDB et qu’un autre à réalisé un résurecteur de site qui, via du contenu récupéré sur archive.org feed un WordPress de manière particulièrement propre. C’est de loin le projet qui m’a le plus impressionné, réalisé par celui qui était le moins Dev de la bande au départ (et qui passait 80h/semaine sur Python), comme quoi tout est possible avec de la volonté !

Et maintenant : la suite du Data-Voyage

L’important dans le Dev, je pense, c’est de pratiquer régulièrement. Souhaitant m’orienter Data quelque chose (ce que j’appelle personnellement du Webmarketing Technique – cela va bien plus loin que le SEO : clustering clients, symbiose SEO/SEA, horodatage des modifs SEO, bandits manchots, marketing automation, personnalisation…), je suis actuellement le programme Python de DataCamp (ça fera l’objet d’un article mais je peux déjà dire que je trouve ça très bien) et une formation Coursera sur les bases mathématiques indispensables pour pouvoir jouer sereinement et sans dire trop de conneries avec de gros dataset. Mon objectif pour 2018 étant de participer à un concours Kaggle.

A court terme, ma prochaine formation va être l’atelier Data SEO des Ix Labs (encore eux !). Je suis aussi pas mal tenté par le programme de formation des Data SEO Labs (aka Vincent Terrassi et Remi Bacha d’OVH) mais pour le moment, le R me rebute (surtout en terme de capacité à apprendre, plus ou moins en parallèle, 2 langages différents et pas mal redondants) même si j’ai un peu évolué sur la question en lisant pas mal de témoignages de devs utilisant Python pour la collecte et le traitement des données et R pour la visualisation (Shiny étant quand même +/- l’outil de DataViz ultime).

Sinon concernant la formation, je l’ai vraiment trouvée très bien, mais parfois un peu trop rapide. J’aimerais bien a terme, pouvoir faire des modules sur 1 journée, histoire d’aller au fond des choses, un module Machine Learning, un module Scraping, un module Pandas… Je crois d’ailleurs que c’est le format retenu pour la future formation R des Ix-Labs.

Mon super code pour analyser les liens de la Google Search Console :

@@ -0,0 +1,115 @@
#récupère les liens issus du rapport Google Search Console
#parse la liste de BL, cherche le lien vers notre site sur la page, cherche l'ancre
#en sortie un rapport avec la répartition des ancres

import csv
import requests
import argparse
from bs4 import BeautifulSoup
from urllib.parse import urlparse, urljoin
from collections import namedtuple, defaultdict
from concurrent.futures import ThreadPoolExecutor

#on commence par récupérer les URL dans le fichier CSV
def csvtolist(gsc_csv_file) :
    with open(gsc_csv_file) as f :
        f_csv = csv.reader(f)
        next(f_csv) #on vire le header
        links = [line[0] for line in f_csv]  # liste qui va contenir les BL
        return links
def linktocrawl(liste_url):
    c = 0


#Fonction NoFollow
def isNofollow(link) :
    if 'nofollow' in str(link) or 'Nofollow' in str(link) :
        return True
    return False

#check des liens internes
def is_internal(url,start_url):
    u = urlparse(url)
    s = urlparse(start_url)
    if (u.netloc == s.netloc):
        return True
    return False

#Ecriture dans un CSV de sortie
def out_csv(url_property_list) :
    with open('out.csv', 'w', newline='') as f:
        f_writer = csv.writer(f)
        header = 'domain,link,anchor,is_no_follow,internal_outlinks,external_outlinks'
        f_writer.writerow(header.split(' '))
        for url_property in url_property_list:
            f_writer.writerow(url_property)

#Transformation de la fonction en class
class myGscCrawler(object) :
    def __init__(self,linklist, domain):
        self.linklist = linklist
        self.domain = domain
        self.count_timeout = 0
        self.count_connect_error = 0
        self.result = []
        self.Url_property = namedtuple('Url_property', 'domain, link, anchor, is_no_follow, internal_outlinks, external_outlinks')
    def check_link(self, url):
        # logique de check d'URL
        try:
            print('URL to crawl :', url)
            r = requests.get(url, verify=False)
        except requests.exceptions.Timeout:
            print('soucis de TimeOut')
            self.count_timeout += 1
        except requests.exceptions.ConnectionError:
            print('Erreur de Connection')
            self.count_connect_error += 1
        soup = BeautifulSoup(r.text, 'lxml')
        ndd = urlparse(url).netloc
        internalLinks = 0
        externalLinks = 0
        if r.status_code != 200:
            # On zappe les pages mortes
            pass
        list_links_ok = []
        for l in soup.body.find_all('a'):
            if not l.has_attr('href'):
                continue
            u = urljoin(url, l['href'])
            u_parse = urlparse(u)
            if is_internal(url, l['href']):
                internalLinks += 1
            else:
                externalLinks += 1
            list_links_ok.append(l)
        for l in list_links_ok :
            u = urljoin(url, l['href'])
            u_parse = urlparse(u)
            if domain in u_parse.netloc:
                print(url, l['href'])
                self.result.append(self.Url_property(ndd, url, l.string, isNofollow(l), internalLinks, externalLinks))

    def check_all(self):
        # on va gérer le pool ici
        pool = ThreadPoolExecutor(128)
        with pool as executor :
            jobs = [executor.submit(self.check_link, url) for url in self.linklist]
        print('timeout :', self.count_timeout, 'Erreur de Connexions :', self.count_connect_error)
        return self.result


if __name__ == "__main__":
    """On réalise un crawler avec requests et bs4 pour les liens dans la GSC"""

    parser = argparse.ArgumentParser()
    parser.add_argument('-d', '--domain', required = True,
                        help = "Le domaine analysé")
    parser.add_argument('-l', '--list', required = True,
                        help ="le fichier exporté depuis GSC")

    args = parser.parse_args()
    domain = args.domain
    links = csvtolist(args.list)
    test = myGscCrawler(links, domain)
    gsclinks = test.check_all()
    out_csv(gsclinks)
By | 2018-01-20T10:45:04+00:00 janvier 18th, 2018|Python|0 Comments

Leave A Comment

Share This