I’m using selenium for the first time to get some information about a fantasy soccer game I play with my friends (we have a competition). I’m facing issues iterating through a list of webelements. Apparently they become stale. Here’s some code and details:
I was able to get to the competition’s page by myself. This page has cards for every team in the competition and they look like this
<span class="cartola-card-thin__nome__time">TEAM1</span>
When clicked, those cards lead to that team’s page. This page contains a dropdown menu that looks like this
<span class="cartola-dropdown-bg__botao cartola-dropdown-bg-botao-rodada-id cartola-dropdown-bg__botao--aberto" ng-class="'cartola-dropdown-bg-botao-' + name"></span>
and this menu contains a div for each round of the competition. It looks like this
<div ng-if="!hasDescription" class="cartola-dropdown-bg__selecao" ng-bind="item.label">rodada 25</div>
When clicked, each div loads that specific team’s formation, and its points during that round. The points are shown on the page like this:
<div class="cartola-time-adv__pontuacao pont-positiva" ng-class="{'pont-positiva': ctrl.timeService.dadosTime.pontos > 0, 'pont-negativa': ctrl.timeService.dadosTime.pontos < 0}" ng-bind="ctrl.timeService.dadosTime.pontos != null ? ctrl.timeService.dadosTime.pontos : ''">78.17</div>
My goal: I want to gather each team’s points during each one of the rounds in a dict[’round’] = points.
What I’ve tried already: I’ve tried to keep the teams in a list by doing
teams = browser.find_elements_by_class_name("cartola-card-thin__nome__time")
Then, for each team in teams I’d click on it. When on that page I’d find each round like this
rounds = browser.find_elements_by_class_name("cartola-dropdown-bg__selecao")
Then, for each round in rounds I’d click on it and get that round’s points.
The problem: those loops where I iterate through teams and rounds are not working because apparently those webelements become stale after the whole process inside the loop (clicking, etc)
How can I approach this problem?
Advertisement
Answer
Angular drop down elements are rebuild in runtime. After drop down is collapsed – previously found drop down item is no longer an element of DOM. It is added to DOM one more time, when drop down is expanded again – but it is not the same element for WebDriver (even if it can be found with the same locator).
So, you’re following this logic:
- Expand drop down
- Get drop down elements ->
teams = browser.find_elements_by_class_name("cartola-card-thin__nome__time")
- Do something for each team -> here, I suppose, that drop down is collapsed. So found WebElements are no longer in DOM -> stale element exception
What you have to do?
teamsCount = len(teams); teamIndexes = range(teamsCount) for(i in temIndexes) team = driver.find_element(locator_that_usesTeamIndex)