Récupérer résultats d'une page internet

Résolu
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

7 réponses

  1. 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
    1. Modérateur
      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 🎶
      1. bravo pour la qualité de ce commentaire
    2. 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
      1. Modérateur
        Ok.
        Pas de souci.
        N'hésitez pas.

        A+
    3. 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
      1. Modérateur
        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
        
    4. 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
      1. Modérateur
        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.
        @++
    5. 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