Selenium操作Angular下拉框:StaleElementReferenceException报错原因解析
问题
尝试用Python Selenium根据获取的值选择Angular下拉框选项,初始代码如下:
elem = driver.find_element('xpath','xpath_value') select = Select(driver.find_element('xpath','//*[@id="qty"]')) select.select_by_visible_text(elem.text) # elem.text的值为1
对应的下拉框HTML代码:
<select ng-disabled="c.data.product.limitPartsQuantity" ng-if="part.dist_channel_status_msg == 'Orderable' && !c.data.isLightUser && part.orderable && !part.part_error" id="qty" name="qty" ng-model="part.quantity" ng-change="c.partSelected(part)" class="ng-valid ng-scope ng-not-empty ng-dirty ng-valid-parse ng-touched" style=""> <option value="0">0</option> <option value="1">1</option> <option value="2">2</option> <option value="3">3</option> <option value="4">4</option> <option value="5">5</option> <option value="6">6</option> <option value="7">7</option> <option value="8">8</option> <option value="9">9</option> <option value="10">10</option> <!-- ngIf: c.data.type=='trade' && c.pcf==false --><option ng-if="c.data.type=='trade' && c.pcf==false" value="15" class="ng-scope" style="">15</option><!-- end ngIf: c.data.type=='trade' && c.pcf==false --> <!-- ngIf: c.data.type=='trade' && c.pcf==false --><option ng-if="c.data.type=='trade' && c.pcf==false" value="20" class="ng-scope">20</option><!-- end ngIf: c.data.type=='trade' && c.pcf==false --> <!-- ngIf: c.data.type=='trade' && c.pcf==false --><option ng-if="c.data.type=='trade' && c.pcf==false" value="25" class="ng-scope">25</option><!-- end ngIf: c.data.type=='trade' && c.pcf==false --> <!-- ngIf: c.data.type=='trade' && c.pcf==false --><option ng-if="c.data.type=='trade' && c.pcf==false" value="30" class="ng-scope">30</option><!-- end ngIf: c.data.type=='trade' && c.pcf==false --> <!-- ngIf: c.data.type=='trade' && c.pcf==false --><option ng-if="c.data.type=='trade' && c.pcf==false" value="50" class="ng-scope">50</option><!-- end ngIf: c.data.type=='trade' && c.pcf==false --> <!-- ngIf: c.data.type=='trade' && c.pcf==false --><option ng-if="c.data.type=='trade' && c.pcf==false" value="75" class="ng-scope">75</option><!-- end ngIf: c.data.type=='trade' && c.pcf==false --> <!-- ngIf: c.data.type=='trade' && c.pcf==false --><option ng-if="c.data.type=='trade' && c.pcf==false" value="100" class="ng-scope">100</option><!-- end ngIf: c.data.type=='trade' && c.pcf==false --> </select>
运行后触发报错:
selenium.common.exceptions.StaleElementReferenceException: Message: stale element reference: element is not attached to the page document
但修改为以下代码后可正常执行:
elem = driver.find_element('xpath','xpath_value') value = elem.text # value = 1 select = Select(driver.find_element('xpath','//*[@id="qty"]')) select.select_by_visible_text(value)
想了解为何两种逻辑相似的代码,前者报错后者正常?
原因分析
- 核心问题出在DOM元素引用的时效性:Selenium获取的
elem是页面DOM元素的直接引用,这个引用仅在元素当前存在于页面DOM树中时有效。 - 第一种写法里,先获取
elem,接着去定位下拉框并初始化Select对象。这个过程中,Angular框架可能因为数据更新、页面重渲染,把之前elem对应的DOM元素移除或替换了。当执行select.select_by_visible_text(elem.text)时,需要再次访问elem的text属性,此时elem已经变成了失效的stale元素,因此抛出异常。 - 第二种写法中,在操作下拉框之前就把
elem.text的内容提取出来存到了本地变量value里,后续只用到这个本地字符串,不再依赖原来的DOM元素引用。哪怕之后elem变成stale,也不会影响已经存在本地的value,所以代码能正常运行。
Angular这类单页框架经常会根据绑定的数据动态更新DOM,元素引用很容易失效,提前把需要的文本、值提取到本地变量是规避这类异常的常用手段。
内容的提问来源于stack exchange,提问作者Abhishek
相关产品推荐
相关产品推荐

