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

Résolu
Patty5083 Messages postés 35 Statut Membre -  
 PHL -
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. Patty5083 Messages postés 35 Statut Membre
     
    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
    0
  2. pijaku Messages postés 13513 Date d'inscription   Statut Modérateur Dernière intervention   2 773
     
    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 🎶
    0
    1. PHL
       
      bravo pour la qualité de ce commentaire
      0
  3. Patty5083 Messages postés 35 Statut Membre
     
    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
    0
    1. pijaku Messages postés 13513 Date d'inscription   Statut Modérateur Dernière intervention   2 773
       
      Ok.
      Pas de souci.
      N'hésitez pas.

      A+
      0
  4. Vous n’avez pas trouvé la réponse que vous recherchez ?

    Posez votre question
  5. Patty5083 Messages postés 35 Statut Membre
     
    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
    0
    1. pijaku Messages postés 13513 Date d'inscription   Statut Modérateur Dernière intervention   2 773
       
      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
      
      0
  6. Patty5083 Messages postés 35 Statut Membre
     
    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
    0
    1. pijaku Messages postés 13513 Date d'inscription   Statut Modérateur Dernière intervention   2 773
       
      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.
      @++
      0
  7. Patty5083 Messages postés 35 Statut Membre
     
    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
    0