如何通过 Selenium 和 WebDriver 等待 JavaScript __doPostBack 调用
How do I wait for a JavaScript __doPostBack call through Selenium and WebDriver
我在尝试填写网站上的两个字段时通过 Selenium/Python 进行自动化时遇到了一种罕见的问题。我的脚本填写了第一个字段,即 ORIGIN CITY 非常好。我已经为第二个字段 WebDriverWait 引入 DELIVERY ADDRESS。
我猜 DELIVERY ADDRESS 字段几乎 可点击 甚至在服务员被引导之前。
但是 ORIGIN CITY 字段有一个 JavaScript 通过 onchange
事件关联如下:
onchange="javascript:setTimeout('__doPostBack(\'DrpCity\',\'\')', 0)"
原城市HTML:
<li>
<div class="form-group">
<select name="DrpCity" onchange="javascript:setTimeout('__doPostBack(\'DrpCity\',\'\')', 0)" id="DrpCity" class="inputStyle">
<option selected="selected" value="0">Origin City</option>
<option value="3">Bangalore</option>
<option value="6">Chennai</option>
<option value="8">Delhi - NCR</option>
<option value="10">Hyderabad</option>
<option value="7">Kochi</option>
<option value="12">Kolkata</option>
<option value="13">Mumbai</option>
<option value="15">Pune</option>
</select>
<span id="ReqCity" style="color:Red;visibility:hidden;">Select your city !</span>
</div>
</li>
送货地址HTML:
<li>
<div class="form-group">
<div class="" id="div_AddPopup" style="display: none;">
*Cars will not be delivered at Metro Stations, Malls or Public Place.
</div>
<input name="txtPickUp" type="text" id="txtPickUp" class="inputStyle locMark" placeholder="Delivery Address" onfocus="showOnKeyPress(); return true;" onblur="hideOnKeyPress(); return true;">
<span id="ReqPickUp" style="color:Red;visibility:hidden;">Enter Delivery Address !</span>
</div>
</li>
一旦 JavaScript 完成,它会清除 DELIVERY ADDRESS 字段中的文本。
我确实查看了 Java 客户的 ExpectedConditions 为 jsReturnsValue,Selenium Python 客户端.
我的代码:
from selenium import webdriver
from selenium.webdriver.support.ui import Select
from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
driver = webdriver.Firefox()
driver.get("https://www.avis.co.in")
mySelect = Select(driver.find_element_by_id("DrpCity"))
mySelect.select_by_visible_text("Pune")
WebDriverWait(driver, 10).until(EC.element_to_be_clickable((By.XPATH,"//input[@id='txtPickUp']"))).send_keys("XYZ")
任何建议都会有所帮助。
我发现,处理这些 JS postbacks
最简单的方法是等待受 load 影响的元素去 陈旧或找不到。
这是一个示例函数:
def waitForElementRemoved(Element, WaitCount, WaitTime):
ElementRemoved = False
WaitTry = 0
while not ElementRemoved:
try:
if WaitTry > WaitCount:
raise Exception("Element not removed from page in alloted time")
Test = Element.text
WaitTry += 1
time.sleep(WaitTime)
except (NoSuchElementException, StaleElementReferenceException):
ElementRemoved = True
然后我会选择一个受此影响的元素 postback load
并将其与一些时间参数一起传递给函数。
如:
driver = webdriver.Firefox()
driver.get("https://www.avis.co.in")
removedElement = driver.find_element_by_id("DrpCity")
mySelect = Select(driver.find_element_by_id("DrpCity"))
mySelect.select_by_visible_text("Pune")
waitForElementRemoved(removedElement, 10, .5)
WebDriverWait(driver, 10).until(EC.element_to_be_clickable((By.XPATH, "//input[@id='txtPickUp']"))).send_keys("XYZ")
我不知道这是不是最好的处理JavaScriptonchange load
事件的方法,但就我而言,它非常有效。
添加到这个答案:我发现等待元素变旧 当有多个加载事件时并不总是有效,我发现使用该方法以及使用下面的代码可以更有效地确保这些动态加载事件是完整的:(我改编了下面的代码 )
# Wait for AJAX (Jquery or JS) dynamic page load events
class DynamicLoadState:
def __call__(self, driver):
LoadComplete = False
JQueryLoadComplete = False
JSLoadComplete = False
try:
if driver.execute_script("return jQuery.active") == 0: JQueryLoadComplete = True
except Exception:
# JQuery is not present on page
JQueryLoadComplete = True
if driver.execute_script("return document.readyState") == 'complete': JSLoadComplete = True
if JQueryLoadComplete and JSLoadComplete: LoadComplete = True
return LoadComplete
def WaitForDynamicLoad(driver, WaitTime):
WebDriverWait(driver, WaitTime).until(DynamicLoadState())
# Use the first method of waiting for the element to go stale
# then run this to make sure all loading is completed
WaitForDynamicLoad(driver, Counts.WaitTime)
希望这有助于防止有人在将来使用 time.sleep()
进行页面加载!
@PixelEinstein 的答案是有效且被接受的答案,他的想法是 等待受负载影响的元素过时或找不到 成功了.最后,我通过比预期更简单的方式找到了解决方案。我不得不简单地等待 DELIVER ADDRESS 字段变为 stale 然后在 DELIVER ADDRESS 上再次调用 'send_keys("XYZ")' 字段如下:
driver.get("https://www.avis.co.in")
mySelect = Select(driver.find_element_by_id("DrpCity"))
mySelect.select_by_visible_text("Pune")
WebDriverWait(driver, 10).until(EC.staleness_of(driver.find_element_by_xpath("//input[@id='txtPickUp']")))
driver.find_element_by_xpath("//input[@id='txtPickUp']").send_keys("XYZ")
讨论 How to wait on the __doPostBack method to complete in javascript? 有助于理解 __doPostBack()
tl;博士
我在尝试填写网站上的两个字段时通过 Selenium/Python 进行自动化时遇到了一种罕见的问题。我的脚本填写了第一个字段,即 ORIGIN CITY 非常好。我已经为第二个字段 WebDriverWait 引入 DELIVERY ADDRESS。
我猜 DELIVERY ADDRESS 字段几乎 可点击 甚至在服务员被引导之前。
但是 ORIGIN CITY 字段有一个 JavaScript 通过 onchange
事件关联如下:
onchange="javascript:setTimeout('__doPostBack(\'DrpCity\',\'\')', 0)"
原城市HTML:
<li>
<div class="form-group">
<select name="DrpCity" onchange="javascript:setTimeout('__doPostBack(\'DrpCity\',\'\')', 0)" id="DrpCity" class="inputStyle">
<option selected="selected" value="0">Origin City</option>
<option value="3">Bangalore</option>
<option value="6">Chennai</option>
<option value="8">Delhi - NCR</option>
<option value="10">Hyderabad</option>
<option value="7">Kochi</option>
<option value="12">Kolkata</option>
<option value="13">Mumbai</option>
<option value="15">Pune</option>
</select>
<span id="ReqCity" style="color:Red;visibility:hidden;">Select your city !</span>
</div>
</li>
送货地址HTML:
<li>
<div class="form-group">
<div class="" id="div_AddPopup" style="display: none;">
*Cars will not be delivered at Metro Stations, Malls or Public Place.
</div>
<input name="txtPickUp" type="text" id="txtPickUp" class="inputStyle locMark" placeholder="Delivery Address" onfocus="showOnKeyPress(); return true;" onblur="hideOnKeyPress(); return true;">
<span id="ReqPickUp" style="color:Red;visibility:hidden;">Enter Delivery Address !</span>
</div>
</li>
一旦 JavaScript 完成,它会清除 DELIVERY ADDRESS 字段中的文本。
我确实查看了 Java 客户的 ExpectedConditions 为 jsReturnsValue,Selenium Python 客户端.
我的代码:
from selenium import webdriver
from selenium.webdriver.support.ui import Select
from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
driver = webdriver.Firefox()
driver.get("https://www.avis.co.in")
mySelect = Select(driver.find_element_by_id("DrpCity"))
mySelect.select_by_visible_text("Pune")
WebDriverWait(driver, 10).until(EC.element_to_be_clickable((By.XPATH,"//input[@id='txtPickUp']"))).send_keys("XYZ")
任何建议都会有所帮助。
我发现,处理这些 JS postbacks
最简单的方法是等待受 load 影响的元素去 陈旧或找不到。
这是一个示例函数:
def waitForElementRemoved(Element, WaitCount, WaitTime):
ElementRemoved = False
WaitTry = 0
while not ElementRemoved:
try:
if WaitTry > WaitCount:
raise Exception("Element not removed from page in alloted time")
Test = Element.text
WaitTry += 1
time.sleep(WaitTime)
except (NoSuchElementException, StaleElementReferenceException):
ElementRemoved = True
然后我会选择一个受此影响的元素 postback load
并将其与一些时间参数一起传递给函数。
如:
driver = webdriver.Firefox()
driver.get("https://www.avis.co.in")
removedElement = driver.find_element_by_id("DrpCity")
mySelect = Select(driver.find_element_by_id("DrpCity"))
mySelect.select_by_visible_text("Pune")
waitForElementRemoved(removedElement, 10, .5)
WebDriverWait(driver, 10).until(EC.element_to_be_clickable((By.XPATH, "//input[@id='txtPickUp']"))).send_keys("XYZ")
我不知道这是不是最好的处理JavaScriptonchange load
事件的方法,但就我而言,它非常有效。
添加到这个答案:我发现等待元素变旧 当有多个加载事件时并不总是有效,我发现使用该方法以及使用下面的代码可以更有效地确保这些动态加载事件是完整的:(我改编了下面的代码
# Wait for AJAX (Jquery or JS) dynamic page load events
class DynamicLoadState:
def __call__(self, driver):
LoadComplete = False
JQueryLoadComplete = False
JSLoadComplete = False
try:
if driver.execute_script("return jQuery.active") == 0: JQueryLoadComplete = True
except Exception:
# JQuery is not present on page
JQueryLoadComplete = True
if driver.execute_script("return document.readyState") == 'complete': JSLoadComplete = True
if JQueryLoadComplete and JSLoadComplete: LoadComplete = True
return LoadComplete
def WaitForDynamicLoad(driver, WaitTime):
WebDriverWait(driver, WaitTime).until(DynamicLoadState())
# Use the first method of waiting for the element to go stale
# then run this to make sure all loading is completed
WaitForDynamicLoad(driver, Counts.WaitTime)
希望这有助于防止有人在将来使用 time.sleep()
进行页面加载!
@PixelEinstein 的答案是有效且被接受的答案,他的想法是 等待受负载影响的元素过时或找不到 成功了.最后,我通过比预期更简单的方式找到了解决方案。我不得不简单地等待 DELIVER ADDRESS 字段变为 stale 然后在 DELIVER ADDRESS 上再次调用 'send_keys("XYZ")' 字段如下:
driver.get("https://www.avis.co.in")
mySelect = Select(driver.find_element_by_id("DrpCity"))
mySelect.select_by_visible_text("Pune")
WebDriverWait(driver, 10).until(EC.staleness_of(driver.find_element_by_xpath("//input[@id='txtPickUp']")))
driver.find_element_by_xpath("//input[@id='txtPickUp']").send_keys("XYZ")
讨论 How to wait on the __doPostBack method to complete in javascript? 有助于理解 __doPostBack()