2A.eco - Web Scrapping et API avec Pocket

Links: notebook, html, PDF, python, slides, GitHub

Le notebook revient sur le webscrapping et l’utilisation d’API avec pocket.

from jyquickhelper import add_notebook_menu
add_notebook_menu()

Objectifs des prochaines séances

Connaissez-vous l’application Pocket ? C’est une application qui simplifie le bookmarking. Elle prend la forme d’une extension Chrome / Firefox. Quand on tombe sur un site intéressant, on peut le bookmaker, et ajouter, ou non, des tags pour “qualifier” le contenu.

Cette application répond au besoin de conserver le contenu web pertinent et de le classer.

Au cours des prochaines séances, nous allons construire un outil de machine learning qui : - se connecte à un compte pocket - récupère les sites bookmarqués et les tags éventuels - à partir des articles taggés, prédit les meilleurs tags des sites non-taggés - tag les articles non taggés

Bref, nous allons concevoir un programme de classification automatique des articles !

Objectif de la séance

  • Créer un compte Pocket
  • S’authentifier auprès de l’API
  • Populer le compte avec des données via l’API
  • Récupérer les données via l’API
  • Scraper les sites bookmarqués pour enrichir les données

Mais c’est quoi une API ?

Donc un API est une interface permettant de communiquer avec une application. En général, on veut récupérer des données. Donc la communication consiste à envoyer une requete HTTP (le plus souvent GET ou POST) et à récupérer des données, souvent au format json. Ici nous voulons récupérer des données d’un compte utilisateur pocket.

Pour savoir comment on communique précisément avec l’API de pocket, il n’y a pas de secret : il faut lire la doc de ceux qui l’ont codée. On vous a simplifié un peu les étapes ci-après.

Création d’un compte Pocket

Créer un compte sur https://getpocket.com/signup?ep=4. Il n’y a pas de vérification d’email, donc vous pouvez mettre un faux mail.

Aller sur la console developer de pocket: https://getpocket.com/developer/apps/index.php

Cliquer sur CREATE AN APPLICATION

Compléter le formulaire comme suit (vous pouvez changer le nom de l’application et la description)

Cliquer sur CREATE APPLICATION

# keyring pour récupérer un mot de passe
import keyring
import os
CONSUMER_KEY = keyring.get_password("web", "ensae_teaching_cs,pocket")
# input pour le demander
# CONSUMER_KEY = input("Insérer ici le CONSUMER KEY de la plateform WEB ")

Vous en aurez besoin pour vous connecter à l’API de pocket.

Authentification

D’abord il faut s’authentifier

Protocole utilisé ici : OAUTH2 (très classique).

6 étapes donc avant d’avoir le droit de récupérer les données. De temps en temps, il existe une librairie python. C’est notre cas : https://github.com/tapanpandita/pocket. On va s’en servir pour s’authentifier. Mais pas pour récupérer les données (elle n’est plus à jour pour faire ça).

Etape 1 : Obtenir un code d’authorisation => get_request_token

import pocket
from pocket import Pocket

REDIRECT_URI = "http://localhost:8888/notebooks/API%20Pocket.ipynb"
# c'est l'url à laquelle vous allez rediriger l'utilisateur (ici, vous) après que pocket a authentifié l'utilisateur (vous)
REQUEST_TOKEN = Pocket.get_request_token(consumer_key=CONSUMER_KEY, redirect_uri=REDIRECT_URI)
# print(REQUEST_TOKEN)

Etape 2: Authoriser l’accès

Il faut le faire à chaque exécution du notebook.

# Enlever les guillemets autour de REQUEST_TOKEN
url = "https://getpocket.com/auth/authorize?request_token={0}&redirect_uri={1}".format("REQUEST_TOKEN", REDIRECT_URI)
print("Aller à l'url : \n" + url)
Aller à l'url :
https://getpocket.com/auth/authorize?request_token=REQUEST_TOKEN&redirect_uri=http://localhost:8888/notebooks/API%20Pocket.ipynb

Cliquer sur Autoriser.

Etape 3: Récupérer le token d’accès

try:
    USER_CREDENTIALS = Pocket.get_credentials(consumer_key=CONSUMER_KEY, code=REQUEST_TOKEN)
except Exception as e:
    print(e)
# print(USER_CREDENTIALS)
ACCESS_TOKEN = USER_CREDENTIALS['access_token']
# print(ACCESS_TOKEN)

Chargement de données sur le nouveau compte

Comme vous venez de créer un compte, vous n’avez pas encore d’articles sauvegardés. On vous a préparé un peu moins de 500 articles (format json). Un tiers de ces articles sont taggés (catégorisés). Un article peut comprendre un ou plusieurs tags.

On vous rappelle que l’objectif à termes sera de prédire les meilleurs tags pour les articles non taggés, étant donnés les mots qui caractérisent ces articles (titre, résumé, et ensemble des mots présents dans le html de la page).

Chargement du fichier json en mémoire

import json

with open('./images/data_pocket.json') as fp:
    data = json.load(fp)

On affiche le premier élément.

from pprint import pprint
keys = list(data.keys())
pprint(data[keys[0]])
{'authors': {'2832761': {'author_id': '2832761',
                         'item_id': '1883956314',
                         'name': 'float',
                         'url': ''}},
 'excerpt': 'Il est impossible d’écrire un programme sans utiliser de '
            'variable. Ce terme désigne le fait d’attribuer un nom ou '
            'identificateur à des informations : en les nommant, on peut '
            'manipuler ces informations beaucoup plus facilement.',
 'favorite': '0',
 'given_title': 'Types et variables du langage python — Programmation avec le '
                'langage Python',
 'given_url': 'http://www.xavierdupre.fr/app/teachpyx/helpsphinx/c_lang/types.html',
 'has_image': '1',
 'has_video': '0',
 'image': {'height': '0',
           'item_id': '1883956314',
           'src': 'http://www.xavierdupre.fr/app/teachpyx/helpsphinx/_images/math/a283b6104f42fc7a8bf845790aa022ac525329f0.png',
           'width': '0'},
 'images': {'1': {'caption': '',
                  'credit': '',
                  'height': '0',
                  'image_id': '1',
                  'item_id': '1883956314',
                  'src': 'http://www.xavierdupre.fr/app/teachpyx/helpsphinx/_images/math/a283b6104f42fc7a8bf845790aa022ac525329f0.png',
                  'width': '0'},
            '2': {'caption': '',
                  'credit': '',
                  'height': '0',
                  'image_id': '2',
                  'item_id': '1883956314',
                  'src': 'http://www.xavierdupre.fr/app/teachpyx/helpsphinx/_images/math/d88bf614100dc9561ab4b951b22f965c77da355d.png',
                  'width': '0'},
            '3': {'caption': '',
                  'credit': '',
                  'height': '0',
                  'image_id': '3',
                  'item_id': '1883956314',
                  'src': 'http://www.xavierdupre.fr/app/teachpyx/helpsphinx/_images/math/e39ddf05c56c382e29aa91aaceca2d5de5c4bd29.png',
                  'width': '0'}},
 'is_article': '0',
 'is_index': '0',
 'item_id': '1883956314',
 'resolved_id': '1883956314',
 'resolved_title': 'Types et variables du langage python¶',
 'resolved_url': 'http://www.xavierdupre.fr/app/teachpyx/helpsphinx/c_lang/types.html',
 'sort_id': 0,
 'status': '0',
 'tags': {'python': {'item_id': '1883956314', 'tag': 'python'}},
 'time_added': '1507548626',
 'time_favorited': '0',
 'time_read': '0',
 'time_updated': '1507548631',
 'word_count': '7921'}

Exercice 1

Chargement des données du json dans le compte nouvellement créé.

Pour communiquer avec une API, il faut envoyer des requêtes HTTP. Ici on veut ajouter les données du fichier json (“given_url” et “tags”) dans le compte Pocket.

Que nous dit la doc ? Consulter https://getpocket.com/developer/docs/v3/add.

Par exemple, pour l’ajout d’un seul item, la doc nous donne l’url à laquelle il faut envoyer une requête (https://getpocket.com/v3/add), et la méthode qu’il faut employer. Ici, il s’agit d’une méthode POST.

Pour envoyer une requête en python, il y a plusieurs solutions. Un des plus simples consiste à utiliser la librairie requests.

A vous de jouer ! Commencez par un seul (par exemple http://docs.python-requests.org/en/master/user/quickstart/ avec les tags “python, requests”), puis si cela a fonctionné, vous pouvez passer 100 items (pas plus, le maximum de requêtes autorisées par l’API est de 500 par heure et par utilisateur).

Pour voir si cela a marché, il suffit d’aller sur votre compte Pocket :)

Récupération des données disponibles dans l’API

Exercice 2

Récupérer les urls et les tags des items qui contiennent le tag “python”.

C’est par ici : https://getpocket.com/developer/docs/v3/retrieve. A vous de jouer !

Exercice 3

Récupérer les urls et les titres des items qui contiennent le mot “python” dans le titre ou l’url

Dans le fichier qui servira à la catégorisation automatique, nous allons avoir besoin : de l’url, du titre, de l’extrait, des tags et du contenu.

L’api ne permet pas d’accéder au contenu des sites épinglés. Mais nous pouvons le récupérer grâce à l’url.

Exercice 4

Constituer d’abord un DataFrame avec les champs resolved_url, resolved_title, excerpt, et les tags des items comprenant le terme python.

Compléter les données avec du webscraping

Beautiful Soup

Reprenons notre liste de sites sur python et analysons le contenu HTML.

from bs4 import BeautifulSoup
from pprint import pprint

#première url de la liste
if 'df' in locals():
    url = df['url'].iloc[0]
    print(url)
else:
    url = "http://www.xavierdupre.fr"

# récupération du contenu (même librairie que pour les requetes api =>
#requests est une librairie qui permet de faire des requetes http, que cela soit pour des api ou du webscraping)

import requests
r = requests.get(url)

#pprint : librairie pour "pretty print" (essayer sans : on voit pas grand chose)
text = r.text if len(r.text) < 1000 else r.text[:1000] + "\n..."
pprint(text)
('<?xml version="1.0" encoding="utf-8"?>n'
 '<html>n'
 '<head>n'
 '<link TYPE="text/css" href="pMenu2.css" rel="stylesheet"/>n'
 '<title>Xavier Dupré, ENSAE, Microsoft</title>n'
 '<meta content="xavier dupré, dupre, ENSAE, Microsoft, Bing, Azure ML, '
 'Azure" name="keywords"/>n'
 '<meta content="text/html; charset=utf-8" http-equiv="Content-Type"/>n'
 '<link rel="shortcut icon" href="pyhome3.ico" />n'
 '<meta content="" name="description" />n'
 '</head>n'
 '<body>n'
 'n'
 '<div class="maintitle">n'
 '<h1>Xavier Duprén'
 '<a href="https://www.linkedin.com/in/xavier-dupr%C3%A9-780924"><img '
 'src="blog/documents/linkedin.png" width="15"/></a>n'
 '<font size="4"><a '
 'href="http://www.xavierdupre.fr/blog/xd_blog_nojs.html">Blog</a></font>n'
 '<a href="blog/xdbrss.xml"><img '
 'src="blog/documents/feed-icon-16x16.png"/></a>n'
 '</h1>n'
 '</div>n'
 'n'
 'n'
 '<div style="position:absolute; top:1%; left:5%; width:120px;">n'
 'n'
 '<p>n'
 '<a style="padding:5px;" '
 'href="app/ensae_teaching_cs/helpsphinx3/index.html"><img '
 'src="app/ensae_teaching_cs/helpsphinx/_static/project_ico.png" width="40px" '
 '/></n'
 '...')
# on stock le contenu html dans la variable html
html = r.text

# on "parse" le html grâce à la librairie beautiful soup
soup = BeautifulSoup(html, "html5lib")

# c'est plus "joli" encore que pprint et surtout,
# il y a plein de méthodes pour extraire les informations que l'on souhaite
soup
<!--?xml version="1.0" encoding="utf-8"?--><html><head>
<link href="pMenu2.css" rel="stylesheet" type="text/css"/>
<title>Xavier Dupré, ENSAE, Microsoft</title>
<meta content="xavier dupré, dupre, ENSAE, Microsoft, Bing, Azure ML, Azure" name="keywords"/>
<meta content="text/html; charset=utf-8" http-equiv="Content-Type"/>
<link href="pyhome3.ico" rel="shortcut icon"/>
<meta content="" name="description"/>
</head>
<body>
<div class="maintitle">
<h1>Xavier Dupré
<a href="https://www.linkedin.com/in/xavier-dupr%C3%A9-780924"><img src="blog/documents/linkedin.png" width="15"/></a>
<font size="4"><a href="http://www.xavierdupre.fr/blog/xd_blog_nojs.html">Blog</a></font>
<a href="blog/xdbrss.xml"><img src="blog/documents/feed-icon-16x16.png"/></a>
</h1>
</div>

<div style="position:absolute; top:1%; left:5%; width:120px;">
<p>
<a href="app/ensae_teaching_cs/helpsphinx3/index.html" style="padding:5px;"><img src="app/ensae_teaching_cs/helpsphinx/_static/project_ico.png" width="40px"/></a>
<a href="app/actuariat_python/helpsphinx/index.html" style="padding:5px;"><img src="app/actuariat_python/helpsphinx/_static/project_ico.png" width="40px"/></a>
<a href="app/ensae_projects/helpsphinx/index.html" style="padding:5px;"><img src="app/ensae_projects/helpsphinx/_static/project_ico.png" width="40px"/></a>
<a href="app/jupytalk/helpsphinx/index.html#jupytalk" style="padding:5px;"><img src="app/jupytalk/helpsphinx/_static/project_ico.png" width="40px"/></a>
</p>
<hr/>
<p>
<a href="http://lesenfantscodaient.fr/" style="padding:5px;"><img src="http://lesenfantscodaient.fr/_static/project_ico.png" width="40px"/></a>
</p>
<hr/>
<p>
<a href="app/mlstatpy/helpsphinx/index.html#mlstatpy" style="padding:5px;"><img src="app/mlstatpy/helpsphinx/_static/project_ico.png" width="40px"/></a>
<a href="app/teachpyx/helpsphinx/index.html#teachpyx" style="padding:5px;"><img src="app/teachpyx/helpsphinx/_static/project_ico.png" width="40px"/></a>
</p>
<hr/>
<p>
<a href="app/pyquickhelper/helpsphinx/index.html" style="padding:5px;"><img src="app/pyquickhelper/helpsphinx/_static/project_ico.png" width="40px"/></a>
<a href="app/pymyinstall/helpsphinx/index.html" style="padding:5px;"><img src="app/pymyinstall/helpsphinx/_static/project_ico.png" width="40px"/></a>
<a href="app/pyensae/helpsphinx/index.html" style="padding:5px;"><img src="app/pyensae/helpsphinx/_static/project_ico.png" width="40px"/></a>
<a href="app/jyquickhelper/helpsphinx/index.html" style="padding:5px;"><img src="app/jyquickhelper/helpsphinx/_static/project_ico.png" width="40px"/></a>
<a href="app/cpyquickhelper/helpsphinx/index.html" style="padding:5px;"><img src="app/cpyquickhelper/helpsphinx/_static/project_ico.png" width="40px"/></a>
<a href="app/pandas_streaming/helpsphinx/index.html" style="padding:5px;"><img src="app/pandas_streaming/helpsphinx/_static/project_ico.png" width="40px"/></a>
</p>
<hr/>
<p>
<a href="app/pymmails/helpsphinx/index.html" style="padding:5px;"><img src="app/pymmails/helpsphinx/_static/project_ico.png" width="40px"/></a>
<a href="app/pyrsslocal/helpsphinx/index.html" style="padding:5px;"><img src="app/pyrsslocal/helpsphinx/_static/project_ico.png" width="40px"/></a>
<a href="app/pysqllike/helpsphinx/index.html" style="padding:5px;"><img src="app/pysqllike/helpsphinx/_static/project_ico.png" width="40px"/></a>
<a href="app/tkinterquickhelper/helpsphinx/index.html" style="padding:5px;"><img src="app/tkinterquickhelper/helpsphinx/_static/project_ico.png" width="40px"/></a>
</p>
<hr/>
<p>
<a href="app/python3_module_template/helpsphinx/index.html" style="padding:5px;"><img src="app/python3_module_template/helpsphinx/_static/project_ico.png" width="40px"/></a>
<a href="app/python3_module_template/helpsphinx2/index.html" style="padding:5px;"><img src="app/python3_module_template/helpsphinx2/_static/project_ico.png" width="40px"/></a>
</p>
</div>
<div style="position:absolute; top:40%; left:75%; ">
<img src="xd_portrait2.jpg" width="250px"/>
</div>
<!-- #################################" -->
<div class="mainbody">
<h3>Enseignements ENSAE / Teachings</h3>

<p>
</p><ul>
<li>    <a href="app/ensae_teaching_cs/helpsphinx3/index.html">Enseignements</a>
        <img src="app/ensae_teaching_cs/helpsphinx3/_static/project_ico.png" width="15px"/>
        <small>
        <a href="app/ensae_teaching_cs/helpsphinx/index.html">version mobile</a>
        </small>
        </li>
<li><a href="app/ensae_teaching_cs/helpsphinx3/ci_status.html">Modules Python pour les enseignements</a>
    <a href="app/pyquickhelper/helpsphinx/index.html"><img src="app/pyquickhelper/helpsphinx/_static/project_ico.png" width="15px"/></a>
    <a href="app/pymyinstall/helpsphinx/index.html"><img src="app/pymyinstall/helpsphinx/_static/project_ico.png" width="15px"/></a>
    <a href="app/pyensae/helpsphinx/index.html"><img src="app/pyensae/helpsphinx/_static/project_ico.png" width="15px"/></a>
    <a href="app/jyquickhelper/helpsphinx/index.html"><img src="app/jyquickhelper/helpsphinx/_static/project_ico.png" width="15px"/></a>
    <a href="app/pymmails/helpsphinx/index.html"><img src="app/pymmails/helpsphinx/_static/project_ico.png" width="15px"/></a>
    <a href="app/pyrsslocal/helpsphinx/index.html"><img src="app/pyrsslocal/helpsphinx/_static/project_ico.png" width="15px"/></a>
    <a href="app/pysqllike/helpsphinx/index.html"><img src="app/pysqllike/helpsphinx/_static/project_ico.png" width="15px"/></a>
    </li>
<li><a href="http://www.xavierdupre.fr/app/teachpyx/helpsphinx/c_resume/python_sheet.html">Résumé de la syntaxe Python</a>
    <a href="app/teachpyx/helpsphinx/index.html#teachpyx"><img src="app/teachpyx/helpsphinx/_static/project_ico.png" width="15px"/></a>
    (<a href="http://www.xavierdupre.fr/site2013/documents/python/resume_utile.pdf">pdf non maintenu</a>)</li>
</ul>
<p></p>
<p>
</p><ul>
<li><a href="app/ensae_teaching_cs/helpsphinx/td_2a.html">Python pour un Data Scientist / Economiste</a>
    <a href="app/ensae_projects/helpsphinx/index.html"><img src="app/ensae_projects/helpsphinx/_static/project_ico.png" width="15px"/></a>
    </li>
<li><a href="app/actuariat_python/helpsphinx/index.html">Python pour un Actuaire</a>
    <a href="app/actuariat_python/helpsphinx/index.html"><img src="app/actuariat_python/helpsphinx/_static/project_ico.png" width="15px"/></a>
    </li>
<li><a href="app/jupytalk/helpsphinx/index.html">Talks, présentations</a>
    <a href="app/jupytalk/helpsphinx/index.html#jupytalk"><img src="app/jupytalk/helpsphinx/_static/project_ico.png" width="15px"/></a>
    </li>
<li><a href="app/teachpyx/helpsphinx/index.html">Apprendre la programmation avec Python</a>
    <a href="app/teachpyx/helpsphinx/index.html#teachpyx"><img src="app/teachpyx/helpsphinx/_static/project_ico.png" width="15px"/></a>
    (en construction)
    <a href="site2013/index_documents.html"><small>Versions précédentes PDF</small></a>
    </li>
<li><a href="app/mlstatpy/helpsphinx/index.html#mlstatpy">Machine Learning, Statistiques et Programmation</a>
    <a href="app/mlstatpy/helpsphinx/index.html#mlstatpy"><img src="app/mlstatpy/helpsphinx/_static/project_ico.png" width="15px"/></a>
    </li>
</ul>
<p></p>
<h3>Programmation pour les enfants</h3>
<p>
</p><ul>
<li><a href="http://lesenfantscodaient.fr/">Les enfants codaient</a>
    <a href="http://lesenfantscodaient.fr/"><img src="http://lesenfantscodaient.fr/_static/project_ico.png" width="15px"/></a>
    </li>
</ul>
<p></p>

<h3>Publications</h3>
<p>
</p><ul>
<li>2009 : <a href="http://www.editions-ellipses.fr/product_info.php?products_id=6891">Programmation avec le langage Python aux Editions Ellipses</a> (actualisation en 2010)</li>
<li>2004 : <a href="http://www.xavierdupre.fr/site2013/these/xd_these.pdf">Thèse : reconnaissance de l'écriture manuscrite</a>,
    <a href="http://www.xavierdupre.fr/site2013/these/these.zip">présentation animée</a></li>
<li>2004 : <a href="http://dl.acm.org/citation.cfm?id=1020787">Hidden Markov models for couples of letters applied to handwriting recognition</a></li>
</ul>
<p></p>

<h3>CV</h3>
<p>
</p><ul>
<li><b>2017 :</b> présentation à Microsoft Experiences <a href="https://experiences17.microsoft.fr/session/5ec43c76-8b50-e711-80c2-000d3a21081a">Deep Learning: choisir son framework et entrainer ses modèles dans Azure</a>
       avec Olivier Grisel</li>
<li><b>2017 :</b> présentation à la <a href="https://www.meshs.fr/page/algorithmes_les_nouveaux_decideurs">Maison européenne des sciences de l'homme et de la société</a></li>
<li><b>2017 :</b> présentation à <a href="http://www.xavierdupre.fr/app/jupytalk/helpsphinx/2017/devoxx2017.html">Devoxx.fr</a></li>
<li><b>2016 :</b> organisation d'un hackathon <a href="http://www.xavierdupre.fr/blog/2016-12-20_nojs.html">ENSAE / EY / La Croix-Rouge / Crésus</a></li>
<li><b>2016 :</b> participation au jury <a href="https://www.etalab.gouv.fr/decouvrez-la-1e-promotion-des-entrepreneurs-dinteret-general">Entrepeneurs d'intérêt général</a></li>
<li><b>2016 :</b> participation à la <a href="http://blog.codeweekfrance.org/best-of-jour-2-4-bordeaux-troyes-le-touquet-vannes-paris-2/">CodeWeek</a> au Touquet</li>
<li><b>2016 :</b> jury et mentor au <a href="http://www.datasciencegame.com/">Data Science Game</a></li>
<li><b>2016 :</b> présentation à <a href="http://pydata.org/paris2016/schedule/">PyData 2016</a></li>
<li><b>2016 :</b> animation de coding goûters avec Microsoft <a href="http://www.leparisien.fr/issy-les-moulineaux-92130/a-issy-les-collegiennes-passent-leurs-vacances-en-colo-numerique-22-04-2016-5737487.php">A Issy, les collégiennes passent leurs vacances en « colo » numérique</a></li>
<li><b>2015 :</b> organisation d'un hackathon <a href="http://www.xavierdupre.fr/blog/2016-04-14_nojs.html">Microsoft / ENSAE / Croix-Rouge</a></li>
<li><b>2015 :</b> invited speaker at <a href="http://www.datalead2015.com/">DataLead 2015</a> in Paris</li>
<li><b>2015 :</b> participation à une table ronde à Dunkerque
            <a href="http://www.urbislemag.fr/big-data-quels-enjeux-et-quels-risques--billet-156-urbis-le-mag.html">Big data et villes intelligentes</a>
            (<a href="exposes/xd_vill_et_numerique_2015.pdf">slides</a>)</li>
<li><b>2015 - today :</b> intervenant, formation <a href="http://www.institutdesactuaires.com/gene/main.php?base=294">Actuaire Data Scientist</a></li>
<li><b>2015 - today :</b> animation de <a href="http://lesenfantscodaient.fr/">coding goûters</a></li>
<li><b>2010 - today :</b> data scientist, Microsoft</li>
<li><b>2000 - today :</b> enseignant, ENSAE</li>
<li><a href="https://www.linkedin.com/in/xavier-dupr%C3%A9-780924">profil Linkedin</a></li>
</ul>
<p></p>
<hr/>
<p class="footnotename">Xavier Dupré
</p>


</div>
<div class="rightbody">

<h3>Digressions</h3>
<p>
</p><ul>
<li><a href="http://www.xavierdupre.fr/site2013/documents/book/index.html">Livres illustrés</a></li>
</ul>
<p></p>



</div>
<script src="http://www.google-analytics.com/urchin.js" type="text/javascript"></script>
<script type="text/javascript">
_uacct = "UA-2815364-1";
urchinTracker();
</script>



</body></html>
type(soup)
bs4.BeautifulSoup

soup est une instance de la classe BeautifulSoup (que l’on a importé de la librairie bs4). C’est une représentation du code html avec des méthodes pratiques, telles que find. find permet de trouver la première occurence d’une balise html qu’on lui passe. Par exemple le 1er lien de la page :

soup.find("a")
<a href="https://www.linkedin.com/in/xavier-dupr%C3%A9-780924"><img src="blog/documents/linkedin.png" width="15"/></a>

Si on veut tous les liens, il faut utiliser findAll. Cela renvoie une objet qui se comporte comme une liste. On peut itérer dessus, ou facilement le transformer en objet “list” (en faisant list())

print(type(soup.findAll("a")))
soup.findAll("a")
<class 'bs4.element.ResultSet'>
[<a href="https://www.linkedin.com/in/xavier-dupr%C3%A9-780924"><img src="blog/documents/linkedin.png" width="15"/></a>,
 <a href="http://www.xavierdupre.fr/blog/xd_blog_nojs.html">Blog</a>,
 <a href="blog/xdbrss.xml"><img src="blog/documents/feed-icon-16x16.png"/></a>,
 <a href="app/ensae_teaching_cs/helpsphinx3/index.html" style="padding:5px;"><img src="app/ensae_teaching_cs/helpsphinx/_static/project_ico.png" width="40px"/></a>,
 <a href="app/actuariat_python/helpsphinx/index.html" style="padding:5px;"><img src="app/actuariat_python/helpsphinx/_static/project_ico.png" width="40px"/></a>,
 <a href="app/ensae_projects/helpsphinx/index.html" style="padding:5px;"><img src="app/ensae_projects/helpsphinx/_static/project_ico.png" width="40px"/></a>,
 <a href="app/jupytalk/helpsphinx/index.html#jupytalk" style="padding:5px;"><img src="app/jupytalk/helpsphinx/_static/project_ico.png" width="40px"/></a>,
 <a href="http://lesenfantscodaient.fr/" style="padding:5px;"><img src="http://lesenfantscodaient.fr/_static/project_ico.png" width="40px"/></a>,
 <a href="app/mlstatpy/helpsphinx/index.html#mlstatpy" style="padding:5px;"><img src="app/mlstatpy/helpsphinx/_static/project_ico.png" width="40px"/></a>,
 <a href="app/teachpyx/helpsphinx/index.html#teachpyx" style="padding:5px;"><img src="app/teachpyx/helpsphinx/_static/project_ico.png" width="40px"/></a>,
 <a href="app/pyquickhelper/helpsphinx/index.html" style="padding:5px;"><img src="app/pyquickhelper/helpsphinx/_static/project_ico.png" width="40px"/></a>,
 <a href="app/pymyinstall/helpsphinx/index.html" style="padding:5px;"><img src="app/pymyinstall/helpsphinx/_static/project_ico.png" width="40px"/></a>,
 <a href="app/pyensae/helpsphinx/index.html" style="padding:5px;"><img src="app/pyensae/helpsphinx/_static/project_ico.png" width="40px"/></a>,
 <a href="app/jyquickhelper/helpsphinx/index.html" style="padding:5px;"><img src="app/jyquickhelper/helpsphinx/_static/project_ico.png" width="40px"/></a>,
 <a href="app/cpyquickhelper/helpsphinx/index.html" style="padding:5px;"><img src="app/cpyquickhelper/helpsphinx/_static/project_ico.png" width="40px"/></a>,
 <a href="app/pandas_streaming/helpsphinx/index.html" style="padding:5px;"><img src="app/pandas_streaming/helpsphinx/_static/project_ico.png" width="40px"/></a>,
 <a href="app/pymmails/helpsphinx/index.html" style="padding:5px;"><img src="app/pymmails/helpsphinx/_static/project_ico.png" width="40px"/></a>,
 <a href="app/pyrsslocal/helpsphinx/index.html" style="padding:5px;"><img src="app/pyrsslocal/helpsphinx/_static/project_ico.png" width="40px"/></a>,
 <a href="app/pysqllike/helpsphinx/index.html" style="padding:5px;"><img src="app/pysqllike/helpsphinx/_static/project_ico.png" width="40px"/></a>,
 <a href="app/tkinterquickhelper/helpsphinx/index.html" style="padding:5px;"><img src="app/tkinterquickhelper/helpsphinx/_static/project_ico.png" width="40px"/></a>,
 <a href="app/python3_module_template/helpsphinx/index.html" style="padding:5px;"><img src="app/python3_module_template/helpsphinx/_static/project_ico.png" width="40px"/></a>,
 <a href="app/python3_module_template/helpsphinx2/index.html" style="padding:5px;"><img src="app/python3_module_template/helpsphinx2/_static/project_ico.png" width="40px"/></a>,
 <a href="app/ensae_teaching_cs/helpsphinx3/index.html">Enseignements</a>,
 <a href="app/ensae_teaching_cs/helpsphinx/index.html">version mobile</a>,
 <a href="app/ensae_teaching_cs/helpsphinx3/ci_status.html">Modules Python pour les enseignements</a>,
 <a href="app/pyquickhelper/helpsphinx/index.html"><img src="app/pyquickhelper/helpsphinx/_static/project_ico.png" width="15px"/></a>,
 <a href="app/pymyinstall/helpsphinx/index.html"><img src="app/pymyinstall/helpsphinx/_static/project_ico.png" width="15px"/></a>,
 <a href="app/pyensae/helpsphinx/index.html"><img src="app/pyensae/helpsphinx/_static/project_ico.png" width="15px"/></a>,
 <a href="app/jyquickhelper/helpsphinx/index.html"><img src="app/jyquickhelper/helpsphinx/_static/project_ico.png" width="15px"/></a>,
 <a href="app/pymmails/helpsphinx/index.html"><img src="app/pymmails/helpsphinx/_static/project_ico.png" width="15px"/></a>,
 <a href="app/pyrsslocal/helpsphinx/index.html"><img src="app/pyrsslocal/helpsphinx/_static/project_ico.png" width="15px"/></a>,
 <a href="app/pysqllike/helpsphinx/index.html"><img src="app/pysqllike/helpsphinx/_static/project_ico.png" width="15px"/></a>,
 <a href="http://www.xavierdupre.fr/app/teachpyx/helpsphinx/c_resume/python_sheet.html">Résumé de la syntaxe Python</a>,
 <a href="app/teachpyx/helpsphinx/index.html#teachpyx"><img src="app/teachpyx/helpsphinx/_static/project_ico.png" width="15px"/></a>,
 <a href="http://www.xavierdupre.fr/site2013/documents/python/resume_utile.pdf">pdf non maintenu</a>,
 <a href="app/ensae_teaching_cs/helpsphinx/td_2a.html">Python pour un Data Scientist / Economiste</a>,
 <a href="app/ensae_projects/helpsphinx/index.html"><img src="app/ensae_projects/helpsphinx/_static/project_ico.png" width="15px"/></a>,
 <a href="app/actuariat_python/helpsphinx/index.html">Python pour un Actuaire</a>,
 <a href="app/actuariat_python/helpsphinx/index.html"><img src="app/actuariat_python/helpsphinx/_static/project_ico.png" width="15px"/></a>,
 <a href="app/jupytalk/helpsphinx/index.html">Talks, présentations</a>,
 <a href="app/jupytalk/helpsphinx/index.html#jupytalk"><img src="app/jupytalk/helpsphinx/_static/project_ico.png" width="15px"/></a>,
 <a href="app/teachpyx/helpsphinx/index.html">Apprendre la programmation avec Python</a>,
 <a href="app/teachpyx/helpsphinx/index.html#teachpyx"><img src="app/teachpyx/helpsphinx/_static/project_ico.png" width="15px"/></a>,
 <a href="site2013/index_documents.html"><small>Versions précédentes PDF</small></a>,
 <a href="app/mlstatpy/helpsphinx/index.html#mlstatpy">Machine Learning, Statistiques et Programmation</a>,
 <a href="app/mlstatpy/helpsphinx/index.html#mlstatpy"><img src="app/mlstatpy/helpsphinx/_static/project_ico.png" width="15px"/></a>,
 <a href="http://lesenfantscodaient.fr/">Les enfants codaient</a>,
 <a href="http://lesenfantscodaient.fr/"><img src="http://lesenfantscodaient.fr/_static/project_ico.png" width="15px"/></a>,
 <a href="http://www.editions-ellipses.fr/product_info.php?products_id=6891">Programmation avec le langage Python aux Editions Ellipses</a>,
 <a href="http://www.xavierdupre.fr/site2013/these/xd_these.pdf">Thèse : reconnaissance de l'écriture manuscrite</a>,
 <a href="http://www.xavierdupre.fr/site2013/these/these.zip">présentation animée</a>,
 <a href="http://dl.acm.org/citation.cfm?id=1020787">Hidden Markov models for couples of letters applied to handwriting recognition</a>,
 <a href="https://experiences17.microsoft.fr/session/5ec43c76-8b50-e711-80c2-000d3a21081a">Deep Learning: choisir son framework et entrainer ses modèles dans Azure</a>,
 <a href="https://www.meshs.fr/page/algorithmes_les_nouveaux_decideurs">Maison européenne des sciences de l'homme et de la société</a>,
 <a href="http://www.xavierdupre.fr/app/jupytalk/helpsphinx/2017/devoxx2017.html">Devoxx.fr</a>,
 <a href="http://www.xavierdupre.fr/blog/2016-12-20_nojs.html">ENSAE / EY / La Croix-Rouge / Crésus</a>,
 <a href="https://www.etalab.gouv.fr/decouvrez-la-1e-promotion-des-entrepreneurs-dinteret-general">Entrepeneurs d'intérêt général</a>,
 <a href="http://blog.codeweekfrance.org/best-of-jour-2-4-bordeaux-troyes-le-touquet-vannes-paris-2/">CodeWeek</a>,
 <a href="http://www.datasciencegame.com/">Data Science Game</a>,
 <a href="http://pydata.org/paris2016/schedule/">PyData 2016</a>,
 <a href="http://www.leparisien.fr/issy-les-moulineaux-92130/a-issy-les-collegiennes-passent-leurs-vacances-en-colo-numerique-22-04-2016-5737487.php">A Issy, les collégiennes passent leurs vacances en « colo » numérique</a>,
 <a href="http://www.xavierdupre.fr/blog/2016-04-14_nojs.html">Microsoft / ENSAE / Croix-Rouge</a>,
 <a href="http://www.datalead2015.com/">DataLead 2015</a>,
 <a href="http://www.urbislemag.fr/big-data-quels-enjeux-et-quels-risques--billet-156-urbis-le-mag.html">Big data et villes intelligentes</a>,
 <a href="exposes/xd_vill_et_numerique_2015.pdf">slides</a>,
 <a href="http://www.institutdesactuaires.com/gene/main.php?base=294">Actuaire Data Scientist</a>,
 <a href="http://lesenfantscodaient.fr/">coding goûters</a>,
 <a href="https://www.linkedin.com/in/xavier-dupr%C3%A9-780924">profil Linkedin</a>,
 <a href="http://www.xavierdupre.fr/site2013/documents/book/index.html">Livres illustrés</a>]

On peut sélectionner des tags qui ont certains attributs css. Par exemple ici, on peut vouloir seulement les liens internes du site. Ils ont la classe “internal”. Les autres “external”.

list(soup.findAll("a", {"class": "internal"}))
[]

Ce n’est pas toujours comme ça, la plupart du temps, il faudra la forme de la valeur de l’attribut href. les liens externes pourront etre identifiés parce qu’ils sont absolus (on indique l’ensemble du lien comme href=“https://docs.python.org/3/reference/expressions.html etc. et non pas un lien relatif comme href=”../c_exception/exception.html (‘..’ signifie « le répertoire parent).

On peut lister toutes les balises h1 et h2 de cette page, en une ligne.

list(soup.findAll({"h1", "h2"}))
[<h1>Xavier Dupré
 <a href="https://www.linkedin.com/in/xavier-dupr%C3%A9-780924"><img src="blog/documents/linkedin.png" width="15"/></a>
 <font size="4"><a href="http://www.xavierdupre.fr/blog/xd_blog_nojs.html">Blog</a></font>
 <a href="blog/xdbrss.xml"><img src="blog/documents/feed-icon-16x16.png"/></a>
 </h1>]

Naviguer vers les enfants

h1 = soup.find("h1")
child = h1.a if h1 else None
child if child else "vide"
<a href="https://www.linkedin.com/in/xavier-dupr%C3%A9-780924"><img src="blog/documents/linkedin.png" width="15"/></a>

Retrouver le parent

child.parent
<h1>Xavier Dupré
<a href="https://www.linkedin.com/in/xavier-dupr%C3%A9-780924"><img src="blog/documents/linkedin.png" width="15"/></a>
<font size="4"><a href="http://www.xavierdupre.fr/blog/xd_blog_nojs.html">Blog</a></font>
<a href="blog/xdbrss.xml"><img src="blog/documents/feed-icon-16x16.png"/></a>
</h1>

Récupérer tous les enfants

children = soup.find("h1").findAll("a")
children
[<a href="https://www.linkedin.com/in/xavier-dupr%C3%A9-780924"><img src="blog/documents/linkedin.png" width="15"/></a>,
 <a href="http://www.xavierdupre.fr/blog/xd_blog_nojs.html">Blog</a>,
 <a href="blog/xdbrss.xml"><img src="blog/documents/feed-icon-16x16.png"/></a>]

Récupérer les attributs des éléments html

[c.attrs for c in children]
[{'href': 'https://www.linkedin.com/in/xavier-dupr%C3%A9-780924'},
 {'href': 'http://www.xavierdupre.fr/blog/xd_blog_nojs.html'},
 {'href': 'blog/xdbrss.xml'}]

Accéder à la valeur d’un attribut en particulier

[c.attrs['href'] for c in children]
['https://www.linkedin.com/in/xavier-dupr%C3%A9-780924',
 'http://www.xavierdupre.fr/blog/xd_blog_nojs.html',
 'blog/xdbrss.xml']

Jusqu’ici, on passe systématiquement par une balise html. Comment faire si on veut récupérer les élements qui ont une class css, quelle que soit la balise html ?

internals = soup.findAll("", {"class": "internal"})
internals
[]

On a presque fini de passer en revue la librairie. Il reste la notion de “sibling”, pratique pour parcourir un tableau. nextSibling : permet de récupérer l’élément html suivant et “de même niveau” dans l’arbre (le prochain frère), previousSibling, le précédent. findChildren permet de trouver tous les enfants.

Enfin la méthode “get_text()” pour récupérer le contenu des balises html. A appliquer en dernier ! En effet, une fois appliquer, on perd toute trace à l’arbre html. SI vous voulez aller plus loin, la doc est bien faite : https://www.crummy.com/software/BeautifulSoup/bs4/doc/

Exercice 5

Récupérer le contenu des code snippets de la page : http://www.xavierdupre.fr/app/teachpyx/helpsphinx/c_lang/types.html

Exercice 6

Récupérer la 3ème colonne (intitulée “exemples”) du tableau des opérateurs : http://www.xavierdupre.fr/app/teachpyx/helpsphinx/c_lang/types.html

Astuce : explorer les CSS selectors : https://www.crummy.com/software/BeautifulSoup/bs4/doc/.

Exercice 7

Récupérer le contenu des titres (h1, h2, h3, etc.) et des balise p de l’ensemble des liens de notre liste et compter le nombre d’occurences du mot python, et la porportion que cela représente dans l’ensemble des mots