Attendez que la window de rechargement lors du défilement de la page Web en VBA

J'ai écrit une macro VBA pour countr le nombre (approximatif) d'images renvoyé pour une search Google d'un terme spécifique. Par approximatif, je veux dire que le programme doit countr le nombre d'images renvoyées, faites défiler vers le bas pour charger un peu plus (le cas échéant) jusqu'à un maximum de 400 images comptées. Voici le code (simplifié):

Sub GoogleCount () ''' '[Code to construct the URL ('fullUrl')] ''' Set objIE = New InternetExplorer objIE.navigate fullUrl Do While objIE.Busy = True Or objIE.readyState <> 4: DoEvents: Loop Set currPage = objIE.document 'Count images returned newNum = currPage.getElementById("rg_s").getElementsByTagName("IMG").Length 'Scroll down until count = 400 (max) or no change in value Do While newNum >= 100 And newNum < 400 And newNum <> oldNum oldNum = newNum currPage.parentWindow.scrollBy 0, 100000 Do While objIE.Busy = True Or objIE.readyState <> 4: DoEvents: Loop newNum = currPage.getElementById("rg_s").getElementsByTagName("IMG").Length Loop ''' '[Code to paste the value of newNum into my workbook, and do some other progress reporting] ''' End Sub 

Je suis mécontent du défilement, il se sent très «manuel» , surtout lorsque vous faites défiler par une valeur fixe (n'importe quel point le rendant dynamic, c'est-à-dire la fin de la page et le défilement) .

Mais le problème principal est que cela ne fonctionne pas: lorsque j'exécute le code, il count les premières 100 (ou less) images bien. Mais quand il est censé faire défiler et countr un peu plus, j'ai la valeur de 100 returnnés. En parcourant lentement le code avec F8, j'obtiens les nombres appropriés (max 400), ce qui me conduit à conclure que le code se déroule trop rapidement (je me trompe peut-être).

Pour ralentir le code, j'ai essayé d'append la boucle de contrôle objIE.readyState , mais parce que je ne fais que défiler, je ne pense pas qu'il count en tant que page de «rechargement», de sorte que la boucle est inefficace en attendant que les nouvelles images soient chargées .

J'ai plutôt pensé à append un timeout à la place. J'emploie déjà

 Private Declare Sub Sleep Lib "kernel32" (ByVal dwMilliseconds As Long) 

ailleurs dans la feuille de calcul – alors, je pourrais append un timeout aussi petit qu'un timeout d'une demi-seconde.

Mais je veux vraiment éviter d'utiliser cela, car ce code fonctionne pour c. 50 searchs différentes et assez longues pour exécuter déjà, append des retards fixes suffisamment longs pour tenir count de la vitesse de connection lente ne serait pas idéal. En outre, les vitesses d'Internet varient tellement qu'un retard fixé est très peu fiable – je pourrais effectuer une sorte de test de connection pour get une meilleure figure de balle-parc, mais la meilleure option est évidemment d'attendre aussi longtime que vous le souhaitez.

Ou mieux encore find une autre façon de countr les images, de preference une qui ne nécessite pas de recharger la page 4 fois! Des idées?

NB. Si vous souhaitez vous https://www.google.com/search?q=stack overflow|exchange&tbm=isch&source=lnt&tbs=isz:ex,iszw:312,iszh:390 , une bonne search d'image pour configurer fullUrl pourrait être https://www.google.com/search?q=stack overflow|exchange&tbm=isch&source=lnt&tbs=isz:ex,iszw:312,iszh:390 car il returnne> 100 images mais less de 400 afin que vous puissiez tester tous les aspects du code

    Il suffit de faire cela, je suis sûr que vous pouvez find un moyen plus agréable de le faire (si vous pensez que ça vaut le time), mais cela devrait être bien:

     newNum = -1 Set objIE = New InternetExplorer objIE.navigate fullUrl Do While objIE.Busy = True Or objIE.readyState <> 4: DoEvents: Loop Set currPage = objIE.document Do Until oldNum = newNum oldNum = newNum newNum = currPage.getElementById("rg_s").getElementsByClassName("rg_di rg_bx rg_el ivg-i").Length Application.Wait Now + TimeSerial(0, 0, 2) currPage.parentWindow.scrollBy 0, 100000 Application.Wait Now + TimeSerial(0, 0, 2) If newNum > 400 Then newNum = 400 Loop newNum = -1 newNum = -1 Set objIE = New InternetExplorer objIE.navigate fullUrl Do While objIE.Busy = True Or objIE.readyState <> 4: DoEvents: Loop Set currPage = objIE.document Do Until oldNum = newNum oldNum = newNum newNum = currPage.getElementById("rg_s").getElementsByClassName("rg_di rg_bx rg_el ivg-i").Length Application.Wait Now + TimeSerial(0, 0, 2) currPage.parentWindow.scrollBy 0, 100000 Application.Wait Now + TimeSerial(0, 0, 2) If newNum > 400 Then newNum = 400 Loop Set objIE = New InternetExplorer newNum = -1 Set objIE = New InternetExplorer objIE.navigate fullUrl Do While objIE.Busy = True Or objIE.readyState <> 4: DoEvents: Loop Set currPage = objIE.document Do Until oldNum = newNum oldNum = newNum newNum = currPage.getElementById("rg_s").getElementsByClassName("rg_di rg_bx rg_el ivg-i").Length Application.Wait Now + TimeSerial(0, 0, 2) currPage.parentWindow.scrollBy 0, 100000 Application.Wait Now + TimeSerial(0, 0, 2) If newNum > 400 Then newNum = 400 Loop objIE.navigate fullUrl newNum = -1 Set objIE = New InternetExplorer objIE.navigate fullUrl Do While objIE.Busy = True Or objIE.readyState <> 4: DoEvents: Loop Set currPage = objIE.document Do Until oldNum = newNum oldNum = newNum newNum = currPage.getElementById("rg_s").getElementsByClassName("rg_di rg_bx rg_el ivg-i").Length Application.Wait Now + TimeSerial(0, 0, 2) currPage.parentWindow.scrollBy 0, 100000 Application.Wait Now + TimeSerial(0, 0, 2) If newNum > 400 Then newNum = 400 Loop Do While objIE.Busy = True Ou objIE.readyState <> 4: DoEvents: Loop newNum = -1 Set objIE = New InternetExplorer objIE.navigate fullUrl Do While objIE.Busy = True Or objIE.readyState <> 4: DoEvents: Loop Set currPage = objIE.document Do Until oldNum = newNum oldNum = newNum newNum = currPage.getElementById("rg_s").getElementsByClassName("rg_di rg_bx rg_el ivg-i").Length Application.Wait Now + TimeSerial(0, 0, 2) currPage.parentWindow.scrollBy 0, 100000 Application.Wait Now + TimeSerial(0, 0, 2) If newNum > 400 Then newNum = 400 Loop Définir currPage = objIE.document newNum = -1 Set objIE = New InternetExplorer objIE.navigate fullUrl Do While objIE.Busy = True Or objIE.readyState <> 4: DoEvents: Loop Set currPage = objIE.document Do Until oldNum = newNum oldNum = newNum newNum = currPage.getElementById("rg_s").getElementsByClassName("rg_di rg_bx rg_el ivg-i").Length Application.Wait Now + TimeSerial(0, 0, 2) currPage.parentWindow.scrollBy 0, 100000 Application.Wait Now + TimeSerial(0, 0, 2) If newNum > 400 Then newNum = 400 Loop Do Until oldNum = newNum newNum = -1 Set objIE = New InternetExplorer objIE.navigate fullUrl Do While objIE.Busy = True Or objIE.readyState <> 4: DoEvents: Loop Set currPage = objIE.document Do Until oldNum = newNum oldNum = newNum newNum = currPage.getElementById("rg_s").getElementsByClassName("rg_di rg_bx rg_el ivg-i").Length Application.Wait Now + TimeSerial(0, 0, 2) currPage.parentWindow.scrollBy 0, 100000 Application.Wait Now + TimeSerial(0, 0, 2) If newNum > 400 Then newNum = 400 Loop oldNum = newNum newNum = -1 Set objIE = New InternetExplorer objIE.navigate fullUrl Do While objIE.Busy = True Or objIE.readyState <> 4: DoEvents: Loop Set currPage = objIE.document Do Until oldNum = newNum oldNum = newNum newNum = currPage.getElementById("rg_s").getElementsByClassName("rg_di rg_bx rg_el ivg-i").Length Application.Wait Now + TimeSerial(0, 0, 2) currPage.parentWindow.scrollBy 0, 100000 Application.Wait Now + TimeSerial(0, 0, 2) If newNum > 400 Then newNum = 400 Loop newNum = currPage.getElementById ("rg_s"). getElementsByClassName ("rg_di rg_bx rg_el ivg-i"). Longueur newNum = -1 Set objIE = New InternetExplorer objIE.navigate fullUrl Do While objIE.Busy = True Or objIE.readyState <> 4: DoEvents: Loop Set currPage = objIE.document Do Until oldNum = newNum oldNum = newNum newNum = currPage.getElementById("rg_s").getElementsByClassName("rg_di rg_bx rg_el ivg-i").Length Application.Wait Now + TimeSerial(0, 0, 2) currPage.parentWindow.scrollBy 0, 100000 Application.Wait Now + TimeSerial(0, 0, 2) If newNum > 400 Then newNum = 400 Loop Application.Wait Now + TimeSerial (0, 0, 2) newNum = -1 Set objIE = New InternetExplorer objIE.navigate fullUrl Do While objIE.Busy = True Or objIE.readyState <> 4: DoEvents: Loop Set currPage = objIE.document Do Until oldNum = newNum oldNum = newNum newNum = currPage.getElementById("rg_s").getElementsByClassName("rg_di rg_bx rg_el ivg-i").Length Application.Wait Now + TimeSerial(0, 0, 2) currPage.parentWindow.scrollBy 0, 100000 Application.Wait Now + TimeSerial(0, 0, 2) If newNum > 400 Then newNum = 400 Loop currPage.parentWindow.scrollBy 0, 100000 newNum = -1 Set objIE = New InternetExplorer objIE.navigate fullUrl Do While objIE.Busy = True Or objIE.readyState <> 4: DoEvents: Loop Set currPage = objIE.document Do Until oldNum = newNum oldNum = newNum newNum = currPage.getElementById("rg_s").getElementsByClassName("rg_di rg_bx rg_el ivg-i").Length Application.Wait Now + TimeSerial(0, 0, 2) currPage.parentWindow.scrollBy 0, 100000 Application.Wait Now + TimeSerial(0, 0, 2) If newNum > 400 Then newNum = 400 Loop Application.Wait Now + TimeSerial (0, 0, 2) newNum = -1 Set objIE = New InternetExplorer objIE.navigate fullUrl Do While objIE.Busy = True Or objIE.readyState <> 4: DoEvents: Loop Set currPage = objIE.document Do Until oldNum = newNum oldNum = newNum newNum = currPage.getElementById("rg_s").getElementsByClassName("rg_di rg_bx rg_el ivg-i").Length Application.Wait Now + TimeSerial(0, 0, 2) currPage.parentWindow.scrollBy 0, 100000 Application.Wait Now + TimeSerial(0, 0, 2) If newNum > 400 Then newNum = 400 Loop Si newNum> 400 Then newNum = 400 newNum = -1 Set objIE = New InternetExplorer objIE.navigate fullUrl Do While objIE.Busy = True Or objIE.readyState <> 4: DoEvents: Loop Set currPage = objIE.document Do Until oldNum = newNum oldNum = newNum newNum = currPage.getElementById("rg_s").getElementsByClassName("rg_di rg_bx rg_el ivg-i").Length Application.Wait Now + TimeSerial(0, 0, 2) currPage.parentWindow.scrollBy 0, 100000 Application.Wait Now + TimeSerial(0, 0, 2) If newNum > 400 Then newNum = 400 Loop 

    Ensuite, il vous suffit d'adapter le timeout dans TimeSerial en fonction de la rapidité avec laquelle votre ordinateur charge (ici je me suis mis à 2 secondes)

    Grâce à de nouvelles searchs, j'ai abordé cette approche:

     Dim myDiv As HTMLDivElement: Set myDiv = currPage.getElementById("fbar") Dim elemRect As IHTMLRect: Set elemRect = myDiv.getBoundingClientRect Do Until elemRect.bottom > 0 currPage.parentWindow.scrollBy 0, 10000 Set elemRect = myDiv.getBoundingClientRect Loop myDiv.ScrollIntoView Dim myDiv comme HTMLDivElement: Définir myDiv = currPage.getElementById ("fbar") Dim myDiv As HTMLDivElement: Set myDiv = currPage.getElementById("fbar") Dim elemRect As IHTMLRect: Set elemRect = myDiv.getBoundingClientRect Do Until elemRect.bottom > 0 currPage.parentWindow.scrollBy 0, 10000 Set elemRect = myDiv.getBoundingClientRect Loop myDiv.ScrollIntoView Dim elemRect As IHTMLRect: Set elemRect = myDiv.getBoundingClientRect Dim myDiv As HTMLDivElement: Set myDiv = currPage.getElementById("fbar") Dim elemRect As IHTMLRect: Set elemRect = myDiv.getBoundingClientRect Do Until elemRect.bottom > 0 currPage.parentWindow.scrollBy 0, 10000 Set elemRect = myDiv.getBoundingClientRect Loop myDiv.ScrollIntoView Do Until elemRect.bottom> 0 Dim myDiv As HTMLDivElement: Set myDiv = currPage.getElementById("fbar") Dim elemRect As IHTMLRect: Set elemRect = myDiv.getBoundingClientRect Do Until elemRect.bottom > 0 currPage.parentWindow.scrollBy 0, 10000 Set elemRect = myDiv.getBoundingClientRect Loop myDiv.ScrollIntoView currPage.parentWindow.scrollBy 0, 10000 Dim myDiv As HTMLDivElement: Set myDiv = currPage.getElementById("fbar") Dim elemRect As IHTMLRect: Set elemRect = myDiv.getBoundingClientRect Do Until elemRect.bottom > 0 currPage.parentWindow.scrollBy 0, 10000 Set elemRect = myDiv.getBoundingClientRect Loop myDiv.ScrollIntoView Définir elemRect = myDiv.getBoundingClientRect Dim myDiv As HTMLDivElement: Set myDiv = currPage.getElementById("fbar") Dim elemRect As IHTMLRect: Set elemRect = myDiv.getBoundingClientRect Do Until elemRect.bottom > 0 currPage.parentWindow.scrollBy 0, 10000 Set elemRect = myDiv.getBoundingClientRect Loop myDiv.ScrollIntoView 

    currPage est la page Web HTML ( Dim currPage As HTMLDocument ) et myDiv est un élément particulier. Le type n'est pas important, mais il convient de noter que myDiv est toujours situé au bas du document et n'est chargé que lorsque tout le rest. Ainsi, pour les images Google, c'est la barre d'aide, que vous n'obtenez qu'après avoir parcouru tous les résultats de l'image.

    Comment ça marche

    Le code fonctionne comme suit: myDiv.getBoundingClientRect est une façon de vérifier si un élément est visible dans le browser – c'est pourquoi nous devons regarder un élément au bas de la page, comme si nous nous défilions jusqu'à ce que ce soit visible, alors tout d'autre doit aussi être chargé.

    C'est bien sûr que le Do Until...Loop vient; nous elemRect.bottom jusqu'à ce que la valeur elemRect.bottom ne soit pas nulle (comme lorsque l'élément n'est pas en vue, c'est nul, une fois qu'il est en vue, il devient un nombre non nul). Plus d'infos sur ça, voir ici

    Enfin, utilisez un myDiv.ScrollIntoView pour accéder au browser vers le bas; Ceci est nécessaire car le BoundingClientRect est légèrement visible avant que l'élément ne soit sur l'écran, il faut donc faire défiler le dernier bit afin de charger les images finales.

    Pourquoi ne pas simplement utiliser ScrollIntoView forment le début? Cela ne fonctionne pas, puisque l'élément n'a pas encore chargé.