Récupérer résultats d'une page internet [Résolu/Fermé]

Messages postés
33
Date d'inscription
lundi 14 avril 2014
Statut
Membre
Dernière intervention
21 mars 2015
- - Dernière réponse :  PHL - 21 juin 2016 à 13:50
Bonjour à tous et bonne année 2015,

Malgré le super tuto de Qwazerty, je n'arrive pas à faire ce que je souhaite.
Je souhaiterais tout simplement cliquer sur Palmarès des numéros dans la page de statistiques Loto de FDJ et récupérer le tableau complet qui s'ouvre alors, puis la même chose avec le Palmarès des Nos de chance
Ma page s'ouvre bien et devient visible, mais je n'obtiens rien... je ne suis donc pas allée plus loin dans le code
Je suis à la retraite et j'ai perdu tous mes réflexes...mais je préfère l'informatique au tricot!!!
J'ai bien coché dans les références du projet VBA :
-Microsoft HTML Object Library et
-Microsoft Internet Controls

Voici le début de mon petit code que je lance par un bouton sur ma feuille Excel

(loto_palmares_nums est un id)

Sub Fdj()
Dim IE As New InternetExplorer
Dim IEDoc As HTMLDocument
Dim InputZoneTexte As HTMLInputElement
Dim InputBouton As HTMLInputElement
Dim htmlGeneric As HTMLGenericElement

'Chargement d'une page Web Google
IE.navigate "www.fdj.fr/jeux/jeux-de-tirage/loto/statistiques"

'Affichage de la fenêtre IE
IE.Visible = True

'On attend le chargement complet de la page
WaitIE IE

'On pointe le membre Document
Set IEDoc = IE.document

IEDoc.all("loto_palmares_nums").Click
End Sub


Si une âme charitable pouvait m'aider, je nage complètement ou plutôt je me noie!!
Merci d'avance à tous


Afficher la suite 

7 réponses

Messages postés
6334
Date d'inscription
jeudi 13 septembre 2007
Statut
Contributeur
Dernière intervention
8 novembre 2019
409
Messages postés
33
Date d'inscription
lundi 14 avril 2014
Statut
Membre
Dernière intervention
21 mars 2015
0
Merci
Bonsoir
Merci pour cette réponse rapide.
Seulement quand je teste le code essai01 cela marche... rapports probables s'ouvre bien... mais je ne vois pas où il va chercher "course-info-plus" :

Set DivParent = IEDoc.getElementById("course-info-plus")

car en affichant le code de la page internet concernée je n'ai pas trouvé cette info et, à mon avis, tout se trouve là....

Merci encore
Messages postés
12253
Date d'inscription
jeudi 15 mai 2008
Statut
Modérateur
Dernière intervention
19 juillet 2019
2215
0
Merci
Bonjour,

Alors.
Analysons les éléments sur lesquels tu souhaites agir.
Pour cela, depuis firefox (je préfères pour sa simplicité), clic droit sur le "lien" (je mets entre guillemets car on ne sait pas si c'est un lien), donc :
clic droit sur le "lien" palmarès des numéros / Examiner l'élément (pour la méthode avec IE se reporter au tuto de QWazerty).

On voit ceci s'afficher :
<div class="ui-accordion-header ui-helper-reset ui-state-default ui-corner-all" onclick="FDJ_tag("loto_fichejeu_stats_palmaresnumeros");" role="tab" aria-expanded="false" tabindex="0" xtcltype="A" xtclib="jeux-de-tirage::loto::statistiques::loto_fichejeu_stats_palmaresnumeros"></div>


Donc l'élément est une div, sans id, mais avec une class, dont le nom est "ui-accordion-header ui-helper-reset ui-state-default ui-corner-all".

On reproduit la même chose avec le second "lien" Palmarès des Nos de chance. On obtient :
<div class="ui-accordion-header ui-helper-reset ui-state-default ui-corner-all" onclick="FDJ_tag("loto_fichejeu_stats_palmaresetoiles");" role="tab" aria-expanded="false" tabindex="0" xtcltype="A" xtclib="jeux-de-tirage::loto::statistiques::loto_fichejeu_stats_palmaresetoiles"></div>


Donc, toujours une div, sans id mais avec une class, dont le nom est "ui-accordion-header ui-helper-reset ui-state-default ui-corner-all".

Par contre, problème, les deux div ont le même nom de class (propriété className pour être bien précis), "ui-accordion-header ui-helper-reset ui-state-default ui-corner-all".
Ce n'est pas grave, on peut les différencier par leur texte (propriété innerText).

Alors, comme nous ne pouvons pas chercher par l'id, on pourrait chercher par la class, grâce à la fonction de qwazerty getElementsByClassName.
On peut également, et je trouve cette méthode plus simple et plus "maniable", enregistrer tous les éléments div de la page dans une collection, grâce à la méthode
GetElementsByTagName
. GetElementsByTagName va lister tous les éléments possédant le même TagName, donc tous les éléments d'une même balise. Nous allons donc lister, grâce à cette méthode, tous les éléments div de notre document.

Voici ce que cela donne après ces petites mais nécessaires explications :

Sub Fdj()
    Dim IE As New InternetExplorer
    Dim IEDoc As HTMLDocument
    Dim ColDeDiv As IHTMLElementCollection
    Dim MaDiv As HTMLGenericElement

    'Chargement d'une page Web Google
   IE.navigate "www.fdj.fr/jeux/jeux-de-tirage/loto/statistiques"
   
   'Affichage de la fenêtre IE
   IE.Visible = True
   
   'On attend le chargement complet de la page
   WaitIE IE
   
   'On pointe le membre Document
   Set IEDoc = IE.document
   'On liste les éléments de type div
   Set ColDeDiv = IEDoc.getElementsByTagName("div")
   'on boucle sur toutes les div
   For Each MaDiv In ColDeDiv
      'si la div a pour className "ui-accordion-head blablabla" alors
      If MaDiv.className = "ui-accordion-header ui-helper-reset ui-state-default ui-corner-all" Then
         'si le texte de la div ne contient pas le mot "chance" alors
         If InStr(MaDiv.innerText, "chance") = 0 Then
            MsgBox "ICI on clic avec la commande : MaDiv.Click" & vbCrLf & "Texte de la div : " & MaDiv.innerText
         'sinon, s'il contient le mot chance
         Else
            MsgBox "ICI on clic avec la commande : MaDiv.Click" & vbCrLf & "Texte de la div : " & MaDiv.innerText
         End If
       End If
   Next
IE.Quit
Set IE = Nothing
End Sub


Nota : pour différencier les deux div, j'ai utilisé Instr avec le mot "chance". En effet, on ne sait pas si le texte restera toujours strictement le même, notamment la partie "octobre 2008"...

EDIT : éventuellement pour qui voudrait tester, j'ajoute la fonction de qwazerty WaitIE :
Sub WaitIE(IE As InternetExplorer)
   'On boucle tant que la page n'est pas totalement chargée
   Do Until IE.ReadyState = READYSTATE_COMPLETE
      DoEvents
   Loop
End Sub


🎼 Cordialement,
Franck 🎶
bravo pour la qualité de ce commentaire
Messages postés
33
Date d'inscription
lundi 14 avril 2014
Statut
Membre
Dernière intervention
21 mars 2015
0
Merci
Bonjour et merci à Pijaku
Super
En effet, cela fonctionne , les tableaux s'ouvrent... Je n'ai plus qu'à essayer de récupérer les données qui s'affichent.
Je crois avoir vu des exemples pour cela et je vais essayer de m'en sortir....
Je vous tiendrai au courant et marquerai "résolu" quand j'aurai tout réussi, sinon je vous demanderai encore de l'aide
Bonne journée à tous
pijaku
Messages postés
12253
Date d'inscription
jeudi 15 mai 2008
Statut
Modérateur
Dernière intervention
19 juillet 2019
2215 -
Ok.
Pas de souci.
N'hésitez pas.

A+
Messages postés
33
Date d'inscription
lundi 14 avril 2014
Statut
Membre
Dernière intervention
21 mars 2015
0
Merci
Bonsoir Pijaku et tous
Je suis désolée... Quand je vois le code html qui s'affiche pour le tableau des palmarès développé... je ne vois pas du tout comment faire, c'est bizarre:
<tr class="odd"></tr>
<tr class="even"></tr>
<tr class="odd"></tr>
<tr class="even"></tr>

et ainsi de suite . La ligne titre, elle, parait claire, mais les données...???

J'ai essayé plusieurs trucs, mais je suis toujours à côté de la plaque...
Je suis complètement larguée
Désolée de vous déranger....et encore merci pour votre dévouement pour aider les autres
Sincèrement
pijaku
Messages postés
12253
Date d'inscription
jeudi 15 mai 2008
Statut
Modérateur
Dernière intervention
19 juillet 2019
2215 -
Salut,
oui, en effet ça n'est pas si simple.
Je t'ai préparé un code, teste le, regarde le, je reviendrais plus tard pour des explications.

Sub Fdj()
    Dim IE As New InternetExplorer
    Dim IEDoc As HTMLDocument
    Dim ColDeDiv As IHTMLElementCollection
    Dim MaDiv As HTMLGenericElement
    Dim Tabl As HTMLTable
    'Chargement d'une page Web Google
   IE.navigate "www.fdj.fr/jeux/jeux-de-tirage/loto/statistiques"
   
   'Affichage de la fenêtre IE
   IE.Visible = True
   
   'On attend le chargement complet de la page
   WaitIE IE
   
   'On pointe le membre Document
   Set IEDoc = IE.document
   'On liste les éléments de type div
   Set ColDeDiv = IEDoc.getElementsByTagName("div")
   'on boucle sur toutes les div
   For Each MaDiv In ColDeDiv
      'si la div a pour className "ui-accordion-head blablabla" alors
      If MaDiv.className = "ui-accordion-header ui-helper-reset ui-state-default ui-corner-all" Then
         'si le texte de la div ne contient pas le mot "Chance" (avec un "C" majuscule) alors
         If InStr(MaDiv.innerText, "Chance") = 0 Then
            MaDiv.Click
            'on cible l'élément <table id="loto_palmares_nums">
            Set Tabl = IEDoc.getElementById("loto_palmares_nums")
            'collecte les éléments de la table et restitue en Sheets("Feuil1").Range("B2")
            TransformTableEnTableau Tabl, Sheets("Feuil1").Range("B2")
         'sinon, s'il contient le mot chance
         Else
            MaDiv.Click
            'on cible l'élément <table id="loto_palmares_chances">
            Set Tabl = IEDoc.getElementById("loto_palmares_chances")
            'collecte les éléments de la table et restitue en Sheets("Feuil1").Range("H2")
            TransformTableEnTableau Tabl, Sheets("Feuil1").Range("H2")
         End If
       End If
   Next
   IE.Quit
   Set IE = Nothing
End Sub

Sub WaitIE(IE As InternetExplorer)
   'On boucle tant que la page n'est pas totalement chargée
   Do Until IE.ReadyState = READYSTATE_COMPLETE
      DoEvents
   Loop
End Sub

Sub TransformTableEnTableau(maTable As HTMLTable, Rng As Range)
'collecte les éléments de la table et restitue en Rng
    Dim Elem As HTMLGenericElement
    Dim ElemFils As HTMLGenericElement
    Dim ElemPetitFils As HTMLGenericElement
    Dim Tb(), i As Integer, j As Integer
    
   'boucle sur tous les éléments de la table
   For Each Elem In maTable.Children
      'si l'élément est de type THEAD (entête d'un tableau HTML)
      If Elem.tagName = "THEAD" Then
        'boucle sur tous les éléments "fils" de THEAD
        For Each ElemFils In Elem.Children
            'Si cet élément est de type TR (ligne d'un tableau HTML)
            If ElemFils.tagName = "TR" Then
                'initialisation d'une variable tableau (VBA)
                i = 1
                ReDim Preserve Tb(1 To 5, 1 To i)
                'boucle sur tous les éléments de la ligne TR
                For Each ElemPetitFils In ElemFils.Children
                    'on stocke ici le contenu de chaque TH (ou TD) (cellule d'un tableau HTML) du TR
                    Tb(i, 1) = ElemPetitFils.innerText
                    i = i + 1
                Next
            End If
        Next
      'IDEM que pour le THEAD, sauf qu'ici on s'occupe du TBODY
      'TBODY étant le "contenu" d'un tableau HTML
      ElseIf Elem.tagName = "TBODY" Then
        j = 2: i = 1
        For Each ElemFils In Elem.Children
            If ElemFils.tagName = "TR" Then
                For Each ElemPetitFils In ElemFils.Children
                    ReDim Preserve Tb(1 To 5, 1 To j)
                    Tb(i, j) = ElemPetitFils.innerText
                    i = i + 1
                Next
            End If
            j = j + 1: i = 1
        Next
      End If
   Next Elem
   With Rng
      .ClearContents
      .Resize(UBound(Tb, 2), UBound(Tb, 1)) = Application.Transpose(Tb)
   End With
End Sub
Messages postés
33
Date d'inscription
lundi 14 avril 2014
Statut
Membre
Dernière intervention
21 mars 2015
0
Merci
Merci à toi.
Cela fonctionne à merveille apparemment.
Je verrai pour adapter à mes colonnes, mais cela me semble un détail à côté du reste...
Je te remercie beaucoup.
Je mettrai ce sujet "résolu" dans les jours qui viennent lorsque tout sera nickel, mais je pense que le pb internet semble résolu...
il faudra que j'essaie de comprendre un peu...
Je verrai dans les jours qui suivent
Encore un super GRAND MERCI à toi
Bonne soirée
pijaku
Messages postés
12253
Date d'inscription
jeudi 15 mai 2008
Statut
Modérateur
Dernière intervention
19 juillet 2019
2215 -
Salut,

Je t'avais promis des explications.

1- pourquoi tu n'as pas réussi :
Tu n'as pas développé l'arborescence dans la fenêtre d'examen de l'élément. Ce qui fait que tu n'as pas vu les données, ni quel élément cibler.

2- ce que j'ai fait :
Dans ce paragraphe, j'ai travaillé sur la table contenant les données des palmarès des numéros. C'est rigoureusement la même chose pour l'autre table.

2a- examiner l'élément concerné par ta recherche :
Pour cela, j'ai fait comme dit précédemment, sous firefox, clic droit sur une partie de l'élément / Examiner l'élément.
Ensuite, j'ai "développé" l'arborescence proposée dans la fenêtre basse de firefox.
J'obtiens ce code html :
<table id="loto_palmares_nums" class="tableErgo tablesorter" cellspacing="0">
    <colgroup></colgroup>
    <thead>
        <tr class="tablesorter-header">
            <th class="cursorPointer tablesorter-header" width="13%" data-column="0">
                <div class="tablesorter-header-inner">
                    Numéros
                </div>
            </th>
            <th class="cursorPointer tablesorter-header" width="22%" data-column="1"></th>
            <!-- etc etc etc -->
        </tr>
    </thead>
    <tbody>
        <tr class="odd">
            <td>
                1
           </td>
          <td>
            115
         </td>
         <td>
             11.5
         </td>
         <td>
             22/11/2014
         </td>
         <td>
              23
         </td>
     </tr>
     <tr class="even">
         <td>
             2
         </td>
         <td>
             98
         </td>
         <td>
             9.8
         </td>
         <td>
             14/01/2015
         </td>
         <td>
             0
         </td>
      </tr>
      <tr class="odd"></tr>
      <tr class="even"></tr>
      <tr class="odd"></tr>
      <tr class="even"></tr>
           <!-- etc etc etc -->
    </tbody>
</table>

On voit ici que les données sont toutes dans des balises
<th>
(titres) et
<td>
(données) sans id et certaines (les th des titres) avec une class...
Bon difficile à importer comme cela.
Nota : th et td = cellule
Remontons dans l'arborescence.
Nous avons, au niveau supérieur des
<tr>
avec une class, soit "odd", soit "even", soit "tablesorter-header".
Encore une fois, difficile à cibler.
Remontons encore.
Nous obtenons cette fois des balises
<thead>
et
<tbody>
sans rien. Ni id, ni class.
Remontons encore.
Cette fois, nous voyons la balise
<table id="loto_palmares_nums" class="tableErgo tablesorter" cellspacing="0">

Nous avons une balise avec un id. On peut donc la cibler.
Les éléments qui sont placés dans des niveaux inférieurs de l'arborescence sont des enfants (et petits-enfants etc) de cette balise <table>.
On peut donc schématiser notre élément comme ceci :
<table id="loto_palmares_nums" >  <!-- parent -->
<thead> <!-- ou <tbody>, enfant de table -->
<tr> <!-- enfant de <thead> (petit-fils de <table>)-->
<th> <!-- ou <td>, enfant de <tr>, petit-fils de <thead> etc -->
<!-- ICI LA DONNEE -->
</th> <!-- ou </td> -->
</tr>
</thead> <!-- ou </tbody> -->
</table>


2b- cibler l'élément :
On fait le choix de cibler l'élément le plus simple à trouver, la balise table qui comporte un id : "loto_palmares_nums".
Pour cela, on utilise :
- une variable de type HTMLTable
- la méthode getElementById.
Comme ceci :
Dim Tabl As HTMLTable
Set Tabl = IEDoc.getElementById("loto_palmares_nums")

Ensuite, il ne reste plus qu'à boucler sur toutes ces balises.

2c- les boucles
Nous allons créer une fonction pour faire tout ce traitement car il va falloir le faire deux fois. Une fois par table (palmarès des numéros ET palmarès des n° Chance). Nous créons donc la fonction
Sub TransformTableEnTableau
à laquelle nous passons deux paramètres :
(maTable As HTMLTable, Rng As Range)
.
- maTable = la table HTML (cf ci-dessus)
- Rng = Range de restitution (cf 2e ci dessous)
Grâce à cet élément de type HTMLTabkle nous allons pouvoir :
- boucler sur les enfants (Children) de table
For Each Elem In maTable.Children
,
- boucler sur les petits-enfants de table (enfants de thead (ou tbody))
For Each ElemFils In Elem.Children

- boucler sur les enfants de tr :
For Each ElemPetitFils In ElemFils.Children


2d- Stockage :
Pour le stockage de ces données on utilise une variable tableau.
- On la redimensionne à la première balise <tr> (ligne des titres) par le code :
ReDim Preserve Tb(1 To 5, 1 To i) 'i étant égal à 1

- On y stocke les données contenues dans les <td> (ou <th>) :
Tb(i, 1) = ElemPetitFils.innerText
i = i + 1

- On la redimensionne, ensuite, à chaque <td> (ou <th>) :
ReDim Preserve Tb(1 To 5, 1 To j)

- On y stocke les données :
Tb(i, j) = ElemPetitFils.innerText
i = i + 1

Sans oublier, à chaque ligne (<tr>) de notre <table> :
- d'incrémenter le j de notre variable tableau,
- de décrémenter le i de notre variable tableau :
j = j + 1: i = 1

En effet, notre variable tableau fonctionne comme ceci :
Tb(i, j)
==> Tb(1, 1), Tb(2, 1), Tb(3, 1), Tb(4, 1), Tb(5, 1) <!-- 1er <tr> -->
==> Tb(1, 2), Tb(2, 2), Tb(3, 2), Tb(4, 2), Tb(5, 2) <!-- 2ème <tr> -->
==> Tb(1, 3), Tb(2, 3), Tb(3, 3), Tb(4, 3), Tb(5, 3) <!-- 3ème <tr> -->
etc...

Un peu à l'inverse de la table html...

2e- restitution des données :
A notre Sub nous avons passé deux paramètres : la table html et un objet Range. Cet objet Range représente la cellule de début de restitution.
Soit :
l'appel de la fonction, dans la Sub principale (fdj) :
TransformTableEnTableau Tabl, Sheets("Feuil1").Range("B2")

va restituer à partir de la cellule Feuil1!B2, grâce à :
Sub TransformTableEnTableau(maTable As HTMLTable, Rng As Range)
   'bla bla bla
   With Rng
      .ClearContents
      .Resize(UBound(Tb, 2), UBound(Tb, 1)) = Application.Transpose(Tb)
   End With
End Sub


Conclusion :

Voilà, désolé de la longueur, mais il fallait bien cela.
N'hésite pas à revenir autant que de besoin pour de plus amples éclaircissements.
@++
Messages postés
33
Date d'inscription
lundi 14 avril 2014
Statut
Membre
Dernière intervention
21 mars 2015
0
Merci
Mille mercis pour ton aide Pijaku.
Cela fonctionne parfaitement, tu es vraiment très fort et surtout très sympathique de prendre du temps pour aider les gens comme moi.
Je te souhaite plein de bonnes choses pour cette nouvelle année.
Je vais voir comment l'on met le sujet résolu
Amicalement