mercredi 19 août 2015

Lecture et analyse d'une page web, téléchargement de fichiers - COURS N°11

Lecture et analyse d'une page web, téléchargement de fichiers

PROBLÉMATIQUE

Ayant recherché des MP3's d'un groupe bien connu qui est les beatles, j'ai enfin trouvé mon bonheur en allant sur mon moteur de recherche préféré via une ligne très simple (pour les habitués).

Code:

intitle:"index of/" beatles mp3
À partir de là je vais sur le lien de l'album que je recherche "With the beatles" et me retrouve à télécharger mes 14 titres de cet album.

Seulement, bof ça me dit pas de faire cela 14 fois, je préfère me coder un petit programme qui me permettra de les télécharger les uns derrière les autres sans que j'ai à bouger le petit doigt (quelle fainéasse :))

Et en plus imaginons que j'en ai 250 à télécharger, vous le feriez 250 fois ? :)

Pour faire cela, je dois passer par plusieurs étapes:
  1. Récupérer la page Web où se trouve mes MP3's
  2. Analyser cette page Web afin d'en ressortir le lien de chacun des MP3's
  3. Joindre l'url de base avec chaque lien
  4. Télécharger le MP3 et le placer dans un répertoire de votre choix sur votre disque dur



Le code que je ferais, sera minimum, on pourrait prendre en compte plusieurs améliorations:
  • La gestion d'erreur (perte de réseau, ...)
  • L'utilisation des arguments de commande pour spécifier les extensions (mp3, avi, ...) qui nous intéressent, mais aussi pour aller plus loin les noms de fichiers, etc...
  • Une interface graphique


et j'en passe...

RÉCUPÉRATION DE LA PAGE WEB

Cela nous permettra d'analyser par la suite la page afin d'en ressortir tous les liens de nos MP3's.

Les modules python utiles sont:
  1. urllib.request et sa méthode read (dans la librairie standard)
  2. lxml (sudo apt-get install python3-lxml)


lxml, c'est quoi ce module ? C'est le module extrêmement puissant dont les petits modules ou même gros comme scrapy s'appuient pour développer l'analyse des pages web.

Oui mais là tu parles de récupération et non d'analyse, pourquoi lxml ?
Simplement pour sa méthode fromstring, qui permettra de rendre le code HTML propre à partir d'une chaîne retournée par la méthode read du module urllib.request !

Comme c'est simple, on est au cours n°11 ;) on va placer le code avec quelques commentaires, ça devrait suffire à votre compréhension.

Code:

from urllib.request import urlopen
from lxml import html # classe html pour travailler avec du HTML

# URL dont tout va partir, on ajoutera nos urls de MP3 à celle-ci
BASE_URL = "http://ift.tt/1E4W20a;

# urlopen pour ouvrir la page, et read pour avoir le résultat sous forme de chaînes de caractères
data = urlopen(BASE_URL).read()

tree = html.fromstring(data) # pour rendre le code HTML propre

tree sera l'arbre de recherche, mais on ne lui a pas dit encore ce qu'on recherchait...

Ce qui nous donne un code HTML (code source de la page)

Code:

<html>
 <head>
  <title>Index of /public/mp3/Beatles/02 With The Beatles</title>
 </head>
 <body>
<h1>Index of /public/mp3/Beatles/02 With The Beatles</h1>
  <table>
  <tr><th valign="top"><img src="/icons/blank.gif" alt="[ICO]"></th><th><a href="?C=N;O=D">Name</a></th><th><a href="?C=M;O=A">Last modified</a></th><th><a href="?C=S;O=A">Size</a></th><th><a href="?C=D;O=A">Description</a></th></tr>
  <tr><th colspan="5"><hr></th></tr>
<tr><td valign="top"><img src="/icons/back.gif" alt="[PARENTDIR]"></td><td><a href="/public/mp3/Beatles/">Parent Directory</a>                                                                                    </td><td> </td><td align="right">  - </td><td> </td></tr>
<tr><td valign="top"><img src="/icons/sound2.gif" alt="[SND]"></td><td><a href="The%20Beatles%20-%20With%20The%20Beatles%20-%2001%20It%20Won't%20Be%20Long%20.mp3">The Beatles - With The Beatles - 01 It Won't Be Long .mp3</a>                                          </td><td align="right">2004-02-11 21:10  </td><td align="right">2.5M</td><td> </td></tr>
<tr><td valign="top"><img src="/icons/sound2.gif" alt="[SND]"></td><td><a href="The%20Beatles%20-%20With%20The%20Beatles%20-%2002%20All%20I've%20Got%20To%20Do.mp3">The Beatles - With The Beatles - 02 All I've Got To Do.mp3</a>                                          </td><td align="right">2004-02-11 21:09  </td><td align="right">2.4M</td><td> </td></tr>
<tr><td valign="top"><img src="/icons/sound2.gif" alt="[SND]"></td><td><a href="The%20Beatles%20-%20With%20The%20Beatles%20-%2003%20All%20My%20Loving.mp3">The Beatles - With The Beatles - 03 All My Loving.mp3</a>                                              </td><td align="right">2004-02-11 21:12  </td><td align="right">2.5M</td><td> </td></tr>
<tr><td valign="top"><img src="/icons/sound2.gif" alt="[SND]"></td><td><a href="The%20Beatles%20-%20With%20The%20Beatles%20-%2004%20Don't%20Bother%20Me.mp3">The Beatles - With The Beatles - 04 Don't Bother Me.mp3</a>                                            </td><td align="right">2004-02-11 21:13  </td><td align="right">2.8M</td><td> </td></tr>
<tr><td valign="top"><img src="/icons/sound2.gif" alt="[SND]"></td><td><a href="The%20Beatles%20-%20With%20The%20Beatles%20-%2005%20Little%20Child.mp3">The Beatles - With The Beatles - 05 Little Child.mp3</a>                                                </td><td align="right">2004-02-11 21:13  </td><td align="right">2.1M</td><td> </td></tr>
<tr><td valign="top"><img src="/icons/sound2.gif" alt="[SND]"></td><td><a href="The%20Beatles%20-%20With%20The%20Beatles%20-%2006%20Till%20There%20Was%20You.mp3">The Beatles - With The Beatles - 06 Till There Was You.mp3</a>                                          </td><td align="right">2004-02-11 21:14  </td><td align="right">2.6M</td><td> </td></tr>
<tr><td valign="top"><img src="/icons/sound2.gif" alt="[SND]"></td><td><a href="The%20Beatles%20-%20With%20The%20Beatles%20-%2007%20Please%20Mister%20Postman.mp3">The Beatles - With The Beatles - 07 Please Mister Postman.mp3</a>                                      </td><td align="right">2004-02-11 21:13  </td><td align="right">3.0M</td><td> </td></tr>
<tr><td valign="top"><img src="/icons/sound2.gif" alt="[SND]"></td><td><a href="The%20Beatles%20-%20With%20The%20Beatles%20-%2008%20Roll%20Over%20Beethoven.mp3">The Beatles - With The Beatles - 08 Roll Over Beethoven.mp3</a>                                        </td><td align="right">2004-02-11 21:13  </td><td align="right">3.2M</td><td> </td></tr>
<tr><td valign="top"><img src="/icons/sound2.gif" alt="[SND]"></td><td><a href="The%20Beatles%20-%20With%20The%20Beatles%20-%2009%20Hold%20Me%20Tight.mp3">The Beatles - With The Beatles - 09 Hold Me Tight.mp3</a>                                              </td><td align="right">2004-02-11 21:13  </td><td align="right">2.9M</td><td> </td></tr>
<tr><td valign="top"><img src="/icons/sound2.gif" alt="[SND]"></td><td><a href="The%20Beatles%20-%20With%20The%20Beatles%20-%2010%20You%20Really%20Got%20A%20Hold%20On%20Me.mp3">The Beatles - With The Beatles - 10 You Really Got A Hold On Me.mp3</a>                                </td><td align="right">2004-02-11 21:14  </td><td align="right">3.5M</td><td> </td></tr>
<tr><td valign="top"><img src="/icons/sound2.gif" alt="[SND]"></td><td><a href="The%20Beatles%20-%20With%20The%20Beatles%20-%2011%20I%20Wanna%20Be%20Your%20Man.mp3">The Beatles - With The Beatles - 11 I Wanna Be Your Man.mp3</a>                                        </td><td align="right">2004-02-11 21:13  </td><td align="right">2.3M</td><td> </td></tr>
<tr><td valign="top"><img src="/icons/sound2.gif" alt="[SND]"></td><td><a href="The%20Beatles%20-%20With%20The%20Beatles%20-%2012%20Devil%20In%20Her%20Heart.mp3">The Beatles - With The Beatles - 12 Devil In Her Heart.mp3</a>                                          </td><td align="right">2004-02-11 21:12  </td><td align="right">2.8M</td><td> </td></tr>
<tr><td valign="top"><img src="/icons/sound2.gif" alt="[SND]"></td><td><a href="The%20Beatles%20-%20With%20The%20Beatles%20-%2013%20Not%20A%20Second%20Time.mp3">The Beatles - With The Beatles - 13 Not A Second Time.mp3</a>                                          </td><td align="right">2004-02-11 21:13  </td><td align="right">2.4M</td><td> </td></tr>
<tr><td valign="top"><img src="/icons/sound2.gif" alt="[SND]"></td><td><a href="The%20Beatles%20-%20With%20The%20Beatles%20-%2014%20Money.mp3">The Beatles - With The Beatles - 14 Money.mp3</a>                                                      </td><td align="right">2004-02-11 21:13  </td><td align="right">3.3M</td><td> </td></tr>
  <tr><th colspan="5"><hr></th></tr>
</table>
</body></html>

ANALYSE DE LA PAGE WEB

La partie la plus complexe, souvent on y va à tâtons, mais avec l'expérience, votre patterns de recherche sera plus précis et vous devrez moins chercher.

Donc analysons notre page HTML et regardons une ligne où se trouve l'url d'un MP3

Code:

<tr><td valign="top"><img src="/icons/sound2.gif" alt="[SND]"></td><td><a href="The%20Beatles%20-%20With%20The%20Beatles%20-%2001%20It%20Won't%20Be%20Long%20.mp3">The Beatles - With The Beatles - 01 It Won't Be Long .mp3</a>
En rouge j'ai mis tout ce dont j'ai besoin pour reconnaître et identifier tous mes MP3's, il faut qu'ils aient ces tags en communs et qu'ils contiennent le terme mp3.

Ici c'est assez simple, pour commencer je vais utiliser la méthode xpath qui me permettra de faire une recherche par pattern.
C'est le pattern qui est plus complexe à trouver, on prendre celui-ci : './/a[contains(text(), "mp3")]/@href' où on dit rechercher à la racine toutes les lignes où se trouvent la balise <a> comprenant le text (text()) mp3.

Pour ce familiariser avec xpath, c'est les essais qui vous aideront, je me souviens avoir chercher au moins deux heures à comprendre son fonctionnement de pattern...

//x -> recherche à la racine la balise x
/x -> recherche la balise suivante x
@x -> recherche toutes les valeurs de la propriété x

Une fois familiarisé, on peut aller beaucoup plus loin, lxml est un module extrêmement puissant !

Bref, après avoir fait plusieurs tests, j'arrive à ce code

Code:

elements = tree.xpath('.//a[contains(text(), "mp3")]/@href')
Plus qu'à récupérer tous les liens de mes MP3's

Code:

for href in elements:
    print(href)

Et là bingo!

Code:

The%20Beatles%20-%20With%20The%20Beatles%20-%2001%20It%20Won't%20Be%20Long%20.mp3
The%20Beatles%20-%20With%20The%20Beatles%20-%2002%20All%20I've%20Got%20To%20Do.mp3
The%20Beatles%20-%20With%20The%20Beatles%20-%2003%20All%20My%20Loving.mp3
The%20Beatles%20-%20With%20The%20Beatles%20-%2004%20Don't%20Bother%20Me.mp3
The%20Beatles%20-%20With%20The%20Beatles%20-%2005%20Little%20Child.mp3
The%20Beatles%20-%20With%20The%20Beatles%20-%2006%20Till%20There%20Was%20You.mp3
The%20Beatles%20-%20With%20The%20Beatles%20-%2007%20Please%20Mister%20Postman.mp3
The%20Beatles%20-%20With%20The%20Beatles%20-%2008%20Roll%20Over%20Beethoven.mp3
The%20Beatles%20-%20With%20The%20Beatles%20-%2009%20Hold%20Me%20Tight.mp3
The%20Beatles%20-%20With%20The%20Beatles%20-%2010%20You%20Really%20Got%20A%20Hold%20On%20Me.mp3
The%20Beatles%20-%20With%20The%20Beatles%20-%2011%20I%20Wanna%20Be%20Your%20Man.mp3
The%20Beatles%20-%20With%20The%20Beatles%20-%2012%20Devil%20In%20Her%20Heart.mp3
The%20Beatles%20-%20With%20The%20Beatles%20-%2013%20Not%20A%20Second%20Time.mp3
The%20Beatles%20-%20With%20The%20Beatles%20-%2014%20Money.mp3

JOINDRE MES URL'S

Pour joindre l'url de base, souvenez-vous de la variable URL_BASE, on va utiliser un module exprès pour cela qui est urllib.parse et sa méthode urljoin.

Code:

url = urljoin(BASE_URL, href)
Voilà url contient mon URL à télécharger, simple non?

TÉLÉCHARGER LE MP3

Pour télécharger l'url on va utiliser la méthode urlretrieve du module urllib.request

Code:

urlretrieve(url, "/home/fred1599/Musique/{}".format(titre))
comme vous voyez j'ai une variable titre, car oui je trouve moche d'avoir enregistré un fichier sous cette forme

Code:

The%20Beatles%20-%20With%20The%20Beatles%20-%2014%20Money.mp3
Je préfère

Code:

The Beatles - With The Beatles - 14 Money.mp3
donc je vais remplacer ces %20 par un caractère d'espacement

Code:

titre = href.replace("%20", " ")
et voilà, nous sommes arrivé à ce que nous voulions et le code final avec tout ça :)

Code:

from urllib.request import urlopen, urlretrieve
from urllib.parse import urljoin
from lxml import html

BASE_URL = "http://ift.tt/1E4W20a;

data = urlopen(BASE_URL).read()

tree = html.fromstring(data)
elements = tree.xpath('.//a[contains(text(), "mp3")]/@href')

count = 0
for href in elements:
        url = urljoin(BASE_URL, href)
        titre = href.replace("%20", " ")
        print("url n°{}: {}".format(count, titre))
        urlretrieve(url, "/home/fred1599/Musique/{}".format(titre))

Comme je l'ai dis c'est un code minimal pour vous faire connaître ce magnifique module qui est lxml...

Merci de m'avoir lu et bonne journée...


from Hackademics : Forum de hacking – hackers white hat – cours de securite informatique, apprendre langage python, tutoriels de reverse engineering http://ift.tt/1gWV4Zm
via IFTTT

Aucun commentaire:

Enregistrer un commentaire