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 = -1newNum = -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 InternetExplorernewNum = -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 fullUrlnewNum = -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: LoopnewNum = -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.documentnewNum = -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 = newNumnewNum = -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 = newNumnewNum = -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"). LongueurnewNum = -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, 100000newNum = -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 = 400newNum = -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.getBoundingClientRectDim 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> 0Dim 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, 10000Dim 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.getBoundingClientRectDim 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
Où 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.
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é.