florentbr / SeleniumBasic

A Selenium based browser automation framework for VB.Net, VBA and VBScript
BSD 3-Clause "New" or "Revised" License
422 stars 197 forks source link

[Selenium VBA Chrome] Timeouterror '21': i guess the loading web page too long #63

Closed jbonneval08 closed 8 years ago

jbonneval08 commented 8 years ago

Hello Florent, First thanks a lot for your great work I am trying to automatize some tasks between Excel 2010/Chrome via windows 7. Chrome version 48.02564.82 m (64-bit) Selenium Basic Type Library => Selenium Basic version 2.0.7.0 Selenium Wrapper Type Library => Selenium Wrapper version 1.0.23.0 Selenium WebDriver Type Library => Selenium Wrapper version 2.44.0.0

My tasks are : 1-Open web with Chrome 2- Copy players list from web site 3- Past in excel sheet. I find out the Selenium code for step 1 2 & 3; BUT Today I face a new issue that is a TimeoutError random timeout error

Erreur d’exécution ‘21’. This timeouterror raised with below code run (I found out it on this forum #50) "```vba" Sub wai()

Dim drv As New ChromeDriver

drv.Timeouts.PageLoad = 4000

If Not drv.Get("https://www.whoscored.com/Teams/256", Raise:=False) Then _ drv.ExecuteScript "window.stop();"

Debug.Assert 0

drv.Quit

End Sub "```"

Message TimeoutError '21' Timeout: Timed out receiving message from renderer: 10.000 (session info: chrome=48.02564.82) (driver info: chromedrvier=2.20.353145 (343b531d31eeb933ec778dbcf7081628a1396067), platform=windows NT 6.1 SP1 x86_64)

The best solution for me is to stop the opening/loading web page as soon as the element id "player-table-statistics-body" is displayed. This element id means the players list is displayed in chrome page. I guess that the right solution is a loop checking this element id is present with high frequency (each second for example) Thanks for your help Jerome

florentbr commented 8 years ago

Your error is probably due to windows.stop(). Moreover there is no need to loop to check the presence of the element, it's done by default and adjustable with the timeout argument:

Dim drv As New ChromeDriver
drv.Timeouts.PageLoad = 5000
drv.Get "https://www.whoscored.com/Teams/256", Raise:=False

Dim tbl As WebElement, values()
Set tbl = drv.FindElementByCss("#top-player-stats-summary-grid", timeout:=10000)
values = tbl.AsTable.data()

' paste the values in excel
[Sheet2!A1].Resize(UBound(values, 1), UBound(values, 2)) = values

Debug.Assert 0
drv.Quit
jbonneval08 commented 8 years ago

Hello Florent,

Many thanks for your fast reply. The code runs but sometimes it raised 1 timeout error erreur execution 7 21

Any idea to avoid this timeout error. I assume the root cause of this timeout is due to slowness network

If no idea, my workaround solution will be

Could you lead me to code this workaround solution?

`

'permet d'aspirer les mins de joueur par equipes
'le numero whoscored des equipes sont dans la sheet todoclas et via selenium on va recuperer     les valeurs sur whoscored automatiquement
Option Explicit
Private TPIEq As String

Sub flo()
Dim RFirst As Long
Dim Rlast As Long
Dim Teamnb As Long
Dim i As Integer
Dim ele As String
Dim Teammissing As String

'identification de la premier ligne du tableau
RFirst = Worksheets("ToDoDSClas").Range("I1").End(xlDown).Row
'identification de la last ligne du tableau
Rlast = Worksheets("ToDoDSClas").Range("I1000").End(xlUp).Row
     'identification de la last ligne pleine du tableau
Rlast = Worksheets("ToDoDSClas").Range("I" & Rlast).End(xlUp).Row

For i = RFirst To Rlast
    Teamnb = Worksheets("ToDoDSClas").Range("I" & i)

    'Dim TPIEq As String
    TPIEq = Worksheets("ToDoDSClas").Range("A" & i)

If Teamnb <> 0 Then
     ele = "https://www.whoscored.com/Teams/" & Teamnb

    Dim drv As New ChromeDriver
    drv.Timeouts.PageLoad = 8000 '5000
    drv.Get ele, Raise:=False

    Dim tbl As WebElement, values()
    Set tbl = drv.FindElementByCss("#top-player-stats-summary-grid", Timeout:=9000) '10000

    'if timeout error

    values = tbl.AsTable.data()

    ' paste the values in excel
    [MI!A2].Resize(UBound(values, 1), UBound(values, 2)) = values
    Call TeamPlayerInteg
    drv.Quit
End If
'    Debug.Assert 0

Next

End Sub

` 2 lasts questions: 1- How know the selemium element match with this html data? help matching => Do you have a website/tips to help me to match html data with Selenium element? 2- Why do you use in your code? it means what? Debug.Assert 0

Again many thanks for your help :) Have a good day Jerome

florentbr commented 8 years ago

Any idea to avoid this timeout error.

Try to increase the timeouts. You could also try to disable the plugins:

Dim drv As New Selenium.ChromeDriver
drv.AddArgument "--disable-plugins-discovery"
drv.SetPreference "plugins.plugins_disabled", Array("Adobe Flash Player")
drv.Get "https://www.whoscored.com/LiveScores"

Could you lead me to code this workaround solution?

A better solution would be to handle the error and try to reload the page.

For t=1 to 3
  On Error Goto TryAgain
  drv.Get "https://www.whoscored.com/LiveScores"
  ...
  Exit For

TryAgain:
Next

How know the selemium element match with this html data?

Selenium can find elements by id, css and xpath. These methods are not specific to selenium and there is plenty of documentation over the web. More over you can easily select the right CSS or XPath in the Chrome Dev Tools with just a right click on the desired element.

Here are 3 examples returning the same element:

Set ele = drv.FindElementById("top-player-stats-summary-grid")
Set ele = drv.FindElementByCss("#top-player-stats-summary-grid")
Set ele = drv.FindElementByXPath("//*[@id='top-player-stats-summary-grid']")

You can also try manually to locate an element in the console of your browser: css : $("#top-player-stats-summary-grid") xpath : $x("//*[@id='top-player-stats-summary-grid']")

2- Why do you use in your code? it means what? Debug.Assert 0

It creates a break point so the browser doesn't close immediately. It is useful for DOM inspection.

100paolo commented 7 years ago

Dec/13/2016

Hi Friends. The Florent's example worked to me with a bit adding.

I'm using: SeleniumBasic-2.0.9.0.exe ChromeDriver 2.26 Excel 2013 64bits Win 7 Pro 64bits Chrome 54.0.2840.99 m

I did what Florent writed: "More over you can easily select the right CSS or XPath in the Chrome Dev Tools with just a right click on the desired element." and so i found the WebElements.

This link was important too: https://mestachs.wordpress.com/2012/08/13/selenium-best-practices/ "Preferred selector order : id > name > css > xpath", you must take the sequencial logic of HTML.

So running Chrome Dev Tools i found a WebElement "tableContainer" wich contains another WebElement "myTable", this is the desired table. And added one more command to the above Florent's example:

Set oWebPg = dSeBot.FindElementByClass("tableContainer", timeout:=500).FindElementById("myTable") values = oWebPg.AsTable.Data() [Sheet1!b20].Resize(UBound(values, 1), UBound(values, 2)) = values

Thank you so much Florent BREHERET.

PBührerDM/BR/SPsp