IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

Python Discussion :

Parser HTML et Beautiful Soup


Sujet :

Python

  1. #1
    Invité
    Invité(e)
    Par défaut Parser HTML et Beautiful Soup
    Bonjour,

    après un passage dans Beautiful Soup d'une page web, voici une partie du code source de la page web :

    Code HTML : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    <table class="rapports">
    <tr class="head">
    <th class="center" colspan="3">Rapports Officiels Loto Foot 15*</th>
    </tr>
    <tr>
    <td>14 sur 14</td><td>3</td><td class="right">333 334*€</td>
    </tr>
    <tr class="row_gtc">
    <td>13 sur 14</td><td>212</td><td class="right">1 221*€</td>
    </tr>
    <tr>
    <td>12 sur 14</td><td>2811</td><td class="right">92,0*€</td>
    </tr>
    <tr class="row_gtc">
    <td>11 sur 14</td><td>18902</td><td class="right">13,6*€</td>
    </tr><tr><td class="small" colspan="3">Gains distribués : 1 774 533*€<br/>* source: fdj.com</td></tr></table><table class="rapports histlf7"><tr class="head"><th>Nombre 1</th><th>Nombre N</th><th>Nombre 2</th></tr><tr><td>7</td><td>5</td><td>2</td></tr></table><table class="rapports"><tr class="head"><th>Cons. 1</th><th>Cons. N</th><th>Cons. 2</th></tr><tr><td>2</td><td>3</td><td>1</td></tr></table><table class="rapports histlf7"><tr class="head"><th>Diagonales</th><th>Symétries</th><th>Alternances</th></tr><tr><td>1</td><td>4</td><td>9</td></tr></table><table class="rapports"><tr class="head"><th>Paires</th><th>Tiercés</th><th>Quartés</th></tr><tr><td>7</td><td>12</td><td>11</td></tr></table>

    J'ai vu avec Beautiful Soup, que je peux récupérer le contenu d'une balise en spécifiant son nom, avec ca :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    combi = htmlsrc.find("table", { "class" : "rapports histlf7" })
    ce code me permet de faire une recherche dans la table rapports histlf7,

    mais dans le code source ci-dessus, on voit qu'il y a 2 tableaux qui se nomment pareil...(rapports histlf7)
    Même problème avec la table class "rapports"

    D'où ma question, comment accéder uniquement au 2ème ?
    Dernière modification par Invité ; 15/10/2014 à 23h33. Motif: Coloration syntaxique [code=HTML] ... [/code]

  2. #2
    Expert éminent
    Homme Profil pro
    Architecte technique retraité
    Inscrit en
    Juin 2008
    Messages
    21 738
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Manche (Basse Normandie)

    Informations professionnelles :
    Activité : Architecte technique retraité
    Secteur : Industrie

    Informations forums :
    Inscription : Juin 2008
    Messages : 21 738
    Par défaut
    Salut,

    Citation Envoyé par jeep05 Voir le message
    D'où ma question, comment accéder uniquement au 2ème ?
    Pour trouver quelque chose, il faut parcourir tout ou partie du document.
    Et le deuxième étant après le premier , il va falloir récupérer la liste de tous les match via .find_all ou au moins les 2 premiers via .find(..., limit=2,...).
    Charge à vous d'ignorer le premier, pour ne récupérer que le 2nd.

    L'utilisation de .find_all et de .find sont documentés ici avec quelques exemples.

    - W
    Architectures post-modernes.
    Python sur DVP c'est aussi des FAQs, des cours et tutoriels

  3. #3
    Invité
    Invité(e)
    Par défaut
    merci pour cette réponse.

    Je réussie à récupérer la table "combinaisons" avec le code suivant :

    Parce qu'il s'agit du premier class "rapports histlf7"

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    htmlsrc = BeautifulSoup.BeautifulSoup(html)
    	#recherche dans la source
    	combi = htmlsrc.find("table", { "class" : "rapports histlf7" })
    	for row in combi.findAll("tr"):
    		cells = row.findAll("td")
    		#For each "tr", assign each "td" to a variable.
    		if len(cells) == 3:
    			Nb1 = cells[0].find(text=True)
    			NbN = cells[1].find(text=True)
    			Nb2 = cells[2].find(text=True)
    			combi = Nb1 + "," + NbN + "," + Nb2 + "\n"
    			print combi

    Mais je n'arrive pas à récupérer celle ci dessous, je n'arrive pas à l'isoler, car table class="rapports" est présent plusieurs fois.
    Je voudrais récupérer, comme je l'ai fait pour les Combinaisons, les 3 chiffres de la table ci dessous.
    Le problème est que rien ne la démarque des autres. Il n'y a pas d'id, de class, ...

    Code HTML : Sélectionner tout - Visualiser dans une fenêtre à part
    <table class="rapports"><tr class="head"><th>Cons. 1</th><th>Cons. N</th><th>Cons. 2</th></tr><tr><td>2</td><td>3</td><td>1</td></tr></table>
    Dernière modification par Invité ; 15/10/2014 à 23h35. Motif: Coloration syntaxique [code=HTML] ... [/code]

  4. #4
    Expert éminent
    Homme Profil pro
    Architecte technique retraité
    Inscrit en
    Juin 2008
    Messages
    21 738
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Manche (Basse Normandie)

    Informations professionnelles :
    Activité : Architecte technique retraité
    Secteur : Industrie

    Informations forums :
    Inscription : Juin 2008
    Messages : 21 738
    Par défaut
    Salut,
    Citation Envoyé par jeep05 Voir le message
    Mais je n'arrive pas à récupérer celle ci dessous, je n'arrive pas à l'isoler, car table class="rapports" est présent plusieurs fois.
    Je voudrais récupérer, comme je l'ai fait pour les Combinaisons, les 3 chiffres de la table ci dessous.
    Je ne comprends pas en quoi cela est si différent du cas précédent.
    Pour choisir le "rapport" qui vous intéresse, il faut probablement d'autres critères mais difficile de les trouver à votre place vu le peu d'informations que vous donnez sur le contenu de la page HTML.
    Désolé.

    - W
    Architectures post-modernes.
    Python sur DVP c'est aussi des FAQs, des cours et tutoriels

  5. #5
    Invité
    Invité(e)
    Par défaut
    Citation Envoyé par wiztricks Voir le message
    Salut,
    Je ne comprends pas en quoi cela est si différent du cas précédent.
    Pour choisir le "rapport" qui vous intéresse, il faut probablement d'autres critères mais difficile de les trouver à votre place vu le peu d'informations que vous donnez sur le contenu de la page HTML.
    Désolé.

    - W
    voici la page en question; A chaque résultats de lotofoot, le site génère une page comme celle ci :
    http://www.pronosoft.com/fr/lotofoot/grille.php?id15=20

    Ce que je souhaite, c'est récupérer les valeurs des 4 petits tableaux pour pouvoir les exporter dans un CSV. Ainsi je pourrai les intégrer facilement dans une feuille de calcul.

    Voici le code que j'ai réussi à écrire pour extraire les 3 chiffres du premier tableau.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
     
    from urllib2 import urlopen
    import bs4 as BeautifulSoup
    url = ("http://www.pronosoft.com/fr/lotofoot/grille.php?id15=20")
    html = urlopen(url).read()
    htmlsrc = BeautifulSoup.BeautifulSoup(html)
    #recherche dans la source
    #recherche de la table combinaisons
    combi = htmlsrc.find("table", { "class" : "rapports histlf7" })
    for row in combi.findAll("tr"):
    	cells = row.findAll("td")
    	#For each "tr", assign each "td" to a variable.
    	if len(cells) == 3:
    		Nb1 = cells[0].find(text=True)
    		NbN = cells[1].find(text=True)
    		Nb2 = cells[2].find(text=True)
    		combi = Nb1 + "," + NbN + "," + Nb2 + "\n"
    		print combi
    #on enregistre le tout dans un fichier
    fichier = open("combinaison.csv", "a")	#on met à jour le fichier
    fichier.write(str(combi))
    fichier.close()
    Ce code me sort : 6,2,7 dans le fichier .csv

    J'aimerai pouvoir, à la suite de 6,2,7 écrire les chiffres des autres tableaux de telle sorte à avoir :
    6,2,7,2,1,2,1,4,11,7,10,12

    Dans la même idée, il faut que j'arrive à travailler sur les tableaux de cette page :
    http://www.pronosoft.com/fr/concours...ot.php?id15=20

    Par exemple je veux pouvoir déterminer dans le tableau "1 les plus joués", combien sont gagnants parmi les 3 plus gros pourcentages. Le plus dur, outre d'extraire les données va être de faire comprendre au programme quand est ce que le résultat est gagnant. (Matérialisé par un fond vert sur le site).
    Dans l'exemple du lien ci-dessus, sur les 3 plus gros pourcentages du 1er tableau, seul 2 sur 3 sont gagnants (Milan AC et Barcelone). Dans ce cas le résultat obtenu doit être 2..

    Peut être en ne regardant que les 3 premières lignes du tableau et parmi celles-ci voir combien ont le fond vert par la balise de couleur..

    Le probleme reste de pouvoir isoler ce tableau des autres. Pareil pour les autres tableaux...

    Autre exemple, dans le tableau Plus grosses surprises, pouvoir compter combien sur les 15 pronostics, s'avèrent gagnants. Ici 3 (fond vert).
    Dernière modification par Invité ; 08/10/2014 à 22h58.

  6. #6
    Expert éminent
    Homme Profil pro
    Architecte technique retraité
    Inscrit en
    Juin 2008
    Messages
    21 738
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Manche (Basse Normandie)

    Informations professionnelles :
    Activité : Architecte technique retraité
    Secteur : Industrie

    Informations forums :
    Inscription : Juin 2008
    Messages : 21 738
    Par défaut
    Salut,

    J'ai regardé vos pages.
    La question est de trouver une heuristique pas trop crade pour en extraire les informations souhaitées.
    note: trouver les tables ou class="rapports histlf7" ne suffit pas.
    C'est du temps à passer à la console et à éditer les pages pour voir et tester sur quoi s'accrocher pour récupérer l'information.
    Il n'y a pas grand chose a coder, sinon apprendre de ses essais erreurs pour arriver à dire "voila comment faire".

    Tant que "comment faire" n'a pas été défini, pas la peine d'essayer de coder.
    Sans vouloir vous vexer, j'ai mieux à faire que de passer mon après midi à faire ce boulot là (plutôt ingrat et assez ch...)

    update/maintenant, c'est le soir
    Si vous jouez à piocher dans le HTML à la console, vous avez:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    >>> for e in bs.findAll("table"):
    ...     print (e['class'])
    ...
    [u'hist_rapports', u'first_rapports']
    [u'rapports']
    [u'rapports', u'histlf7']  #<-- 1ere table "of interest"
    [u'rapports']                #<-- 2nd
    [u'rapports', u'histlf7']  #<-- 3rd
    [u'rapports']                #<-- 4th
    Une heuristique "cheap" pourrait être de dire "les résultats intéressants sont dans les 4 dernières tables".
    Après il faut voir si toutes les pages ont une structure similaire.

    - W
    Architectures post-modernes.
    Python sur DVP c'est aussi des FAQs, des cours et tutoriels

  7. #7
    Invité
    Invité(e)
    Par défaut
    Citation Envoyé par wiztricks Voir le message
    Salut,
    J'ai regardé vos pages.
    La question est de trouver une heuristique pas trop crade pour en extraire les informations souhaitées.
    note: trouver les tables ou class="rapports histlf7" ne suffit pas.
    C'est du temps à passer à la console et à éditer les pages pour voir et tester sur quoi s'accrocher pour récupérer l'information.
    Il n'y a pas grand chose a coder, sinon apprendre de ses essais erreurs pour arriver à dire "voila comment faire".

    Tant que "comment faire" n'a pas été défini, pas la peine d'essayer de coder.
    Sans vouloir vous vexer, j'ai mieux à faire que de passer mon après midi à faire ce boulot là (plutôt ingrat et assez ch...)
    Je comprends le raisonnement et le partage. C'est ce que je me dit. Comment faire ;-)

    Merci de participer au sujet, c'est déjà avancer pour moi.

    Dès que j'en ai le temps, je me penche sur le morceau de code suggéré.

    Je pourrais donc lister les tableaux de la page en filtrant au mieux, puis les numéroter et ainsi accéder au tableau que je veux en l'identifiant par son numéro ?
    Dernière modification par Invité ; 09/10/2014 à 20h53.

  8. #8
    Expert éminent
    Homme Profil pro
    Architecte technique retraité
    Inscrit en
    Juin 2008
    Messages
    21 738
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Manche (Basse Normandie)

    Informations professionnelles :
    Activité : Architecte technique retraité
    Secteur : Industrie

    Informations forums :
    Inscription : Juin 2008
    Messages : 21 738
    Par défaut
    Salut,

    Citation Envoyé par jeep05 Voir le message
    Je pourrais donc lister les tableaux de la page en filtrant au mieux, puis les numéroter et ainsi accéder au tableau que je veux en l'identifiant par son numéro ?
    Dans ce cas particulier, 'bs.findAll("table")' retourne une liste de N=6 éléments.
    Et récupérer les 4 derniers éléments d'une liste est une opération de base:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    >>> L = range(10) # une liste fabriquée vite fait
    >>> L
    [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
    >>> L[-4:]  # les 4 derniers
    [6, 7, 8, 9]
    >>>
    - W
    Architectures post-modernes.
    Python sur DVP c'est aussi des FAQs, des cours et tutoriels

  9. #9
    Invité
    Invité(e)
    Par défaut
    Merci !
    Je vais creuser dans ce sens ;-)

  10. #10
    Invité
    Invité(e)
    Par défaut
    Bonjour,

    j'ai bien progressé depuis la dernière fois.

    Je suis bloqué par le cas suivant
    Grâce à BeautifulSoup j'arrive à travailler sur cette partie :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    <td class="stat_pourc" style="background:#cb281c;color:#fff;">89,5</td>
    <td class="stat_pourc" style="background:#70a745;color:#fff;">85,2</td>
    <td class="stat_pourc" style="background:#cb281c;color:#fff;">76,0</td>
    <td class="stat_pourc" style="background:#70a745;color:#fff;">68,7</td>
    <td class="stat_pourc" style="background:#70a745;color:#fff;">62,4</td>
    <td class="stat_pourc" style="background:#cb281c;color:#fff;">58,6</td>
    <td class="stat_pourc" style="background:#70a745;color:#fff;">48,9</td>
    <td class="stat_pourc" style="background:#cb281c;color:#fff;">47,8</td>
    <td class="stat_pourc" style="background:#cb281c;color:#fff;">47,3</td>
    <td class="stat_pourc" style="background:#70a745;color:#fff;">39,9</td>
    <td class="stat_pourc" style="background:#cb281c;color:#fff;">34,6</td>
    <td class="stat_pourc" style="background:#70a745;color:#fff;">25,2</td>
    <td class="stat_pourc" style="background:#cb281c;color:#fff;">13,5</td>
    <td class="stat_pourc" style="background:#cb281c;color:#fff;">11,0</td>
    Je souhaite les distinguer par la valeur de background qui différencie les résultats gagnants des perdants..

    Je n'y arrive pas.

    Le if matchs.find("70a745"): ne fonctionne pas. Je comprends pas pourquoi il renvoie 14 alors qu'il n'y a que 6 lignes qui comportent "70a745"

    .find ne fonctionne pas. J'ai l'impression qu'il ne s'applique qu'au contenu de la cellule td soit les nombres.


    voici le code :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    for e in htmlsrc.findAll("table", { "class" : "stat_rapports" })[4:5]: #on isole le tableau qu'on veut traiter
    	for ligne in e.findAll("tr")[:16]:	#on regarde chaque ligne - parmi les 14
    		cellules = ligne.findAll("td")	
    		if len(cellules) == 3:
    			matchs = cellules[2]		
    			print matchs
    			matchs = matchs.get('style')
    			matchs = str(matchs)
    			print matchs
    			if matchs.find("70a745"):	
    				nbregagnants += 1						#on compte le nbre de % gagnant
     
    print nbregagnants
    J'ai essayé d'isoler le contenu de style avec .get() mais ca ne va pas.

    Avec le code ci-dessus j'ai le résultat suivant :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    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
    <td class="stat_pourc" style="background:#cb281c;color:#fff;">89,5</td>
    background:#cb281c;color:#fff;
    <td class="stat_pourc" style="background:#70a745;color:#fff;">85,2</td>
    background:#70a745;color:#fff;
    <td class="stat_pourc" style="background:#cb281c;color:#fff;">76,0</td>
    background:#cb281c;color:#fff;
    <td class="stat_pourc" style="background:#70a745;color:#fff;">68,7</td>
    background:#70a745;color:#fff;
    <td class="stat_pourc" style="background:#70a745;color:#fff;">62,4</td>
    background:#70a745;color:#fff;
    <td class="stat_pourc" style="background:#cb281c;color:#fff;">58,6</td>
    background:#cb281c;color:#fff;
    <td class="stat_pourc" style="background:#70a745;color:#fff;">48,9</td>
    background:#70a745;color:#fff;
    <td class="stat_pourc" style="background:#cb281c;color:#fff;">47,8</td>
    background:#cb281c;color:#fff;
    <td class="stat_pourc" style="background:#cb281c;color:#fff;">47,3</td>
    background:#cb281c;color:#fff;
    <td class="stat_pourc" style="background:#70a745;color:#fff;">39,9</td>
    background:#70a745;color:#fff;
    <td class="stat_pourc" style="background:#cb281c;color:#fff;">34,6</td>
    background:#cb281c;color:#fff;
    <td class="stat_pourc" style="background:#70a745;color:#fff;">25,2</td>
    background:#70a745;color:#fff;
    <td class="stat_pourc" style="background:#cb281c;color:#fff;">13,5</td>
    background:#cb281c;color:#fff;
    <td class="stat_pourc" style="background:#cb281c;color:#fff;">11,0</td>
    background:#cb281c;color:#fff;
    14

  11. #11
    Expert éminent
    Homme Profil pro
    Architecte technique retraité
    Inscrit en
    Juin 2008
    Messages
    21 738
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Manche (Basse Normandie)

    Informations professionnelles :
    Activité : Architecte technique retraité
    Secteur : Industrie

    Informations forums :
    Inscription : Juin 2008
    Messages : 21 738
    Par défaut
    Salut,

    A la ligne 7, matchs.get('style') vous retourne une chaîne de caractères.
    Et str.find vous retourne l'index de la chaine qu'il trouve ou -1.
    Le résultat sera, dans votre cas, toujours non nul et donc toujours "True".
    Remplacez "if matchs.find("70a745"):" par "if "70a745" in matchs:"

    - W
    Architectures post-modernes.
    Python sur DVP c'est aussi des FAQs, des cours et tutoriels

  12. #12
    Invité
    Invité(e)
    Par défaut
    Citation Envoyé par wiztricks Voir le message
    Salut,

    Remplacez "if matchs.find("70a745"):" par "if "70a745" in matchs:"

    - W
    Merci W.

    C'est excellent.
    Ca fonctionne. Je continue...

Discussions similaires

  1. [HELP] Modélisation d'un parser HTML
    Par dazulu dans le forum Langages de programmation
    Réponses: 11
    Dernier message: 31/07/2006, 01h03
  2. [VB]parser HTML
    Par wehtam dans le forum VB 6 et antérieur
    Réponses: 8
    Dernier message: 31/01/2006, 23h26
  3. Parser HTML
    Par Mucsy dans le forum MFC
    Réponses: 3
    Dernier message: 02/01/2006, 15h49
  4. [Système] Existe-t-il un bon parser HTML pour PHP ?
    Par MiJack dans le forum Langage
    Réponses: 8
    Dernier message: 25/10/2005, 11h18
  5. [Parser HTML] quel parser utiliser pour du HTML 4.0 ?
    Par Cyber@l dans le forum API standards et tierces
    Réponses: 5
    Dernier message: 19/07/2004, 19h32

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo