आप सेलेनियम 2.0 कैसे लोड करने के लिए पेज का इंतजार करते हैं?
आप सेलेनियम 2.0 कैसे लोड करने के लिए पेज का इंतजार करते हैं?
जवाबों:
आप निम्नलिखित कोड का उपयोग करके पगेलोएड भी देख सकते हैं
IWait<IWebDriver> wait = new OpenQA.Selenium.Support.UI.WebDriverWait(driver, TimeSpan.FromSeconds(30.00));
wait.Until(driver1 => ((IJavaScriptExecutor)driver).ExecuteScript("return document.readyState").Equals("complete"));
वर्ग WebDriverWait का उपयोग करें
यहां भी देखें
आप कुछ तत्व दिखाने की उम्मीद कर सकते हैं। C # में कुछ इस तरह:
WebDriver _driver = new WebDriver();
WebDriverWait _wait = new WebDriverWait(_driver, new TimeSpan(0, 1, 0));
_wait.Until(d => d.FindElement(By.Id("Id_Your_UIElement"));
यदि आप ड्राइवर के निहित इंतजार को निर्धारित करते हैं, तो जिस findElement
तत्व को आप लोड किए गए पृष्ठ पर होने की उम्मीद करते हैं, उस विधि पर कॉल करें , वेबड्राइवर उस तत्व के लिए मतदान करेगा जब तक कि वह तत्व नहीं ढूंढता है या समय आउट मान तक नहीं पहुंचता है।
driver.manage().timeouts().implicitlyWait(10, TimeUnit.SECONDS);
source: निहित-प्रतीक्षा
सामान्य तौर पर, सेलेनियम 2.0 के साथ वेब ड्राइवर को केवल कॉलिंग कोड पर नियंत्रण वापस करना चाहिए, क्योंकि यह निर्धारित किया गया है कि पृष्ठ लोड हो गया है। यदि ऐसा नहीं होता है, तो आप कॉल कर सकते हैं waitforelemement
, जो चक्र कॉलिंग को findelement
तब तक प्राप्त करता है जब तक कि यह नहीं मिलता है या टाइम आउट (टाइम आउट सेट किया जा सकता है)।
If click() causes a new page to be loaded via an event or is done by sending a native event (which is a common case on Firefox, IE on Windows) then the method will not wait for it to be loaded and the caller should verify that a new page has been loaded.
JavascriptExecutor
, "पूर्ण" होने के लिए document.readyState की प्रतीक्षा कर रहा है । सेलेनियम से ब्राउज़र तक राउंड ट्रिप की वजह से, दौड़ की स्थिति का अनुमान लगाया गया है, और यह "हमेशा" मेरे लिए काम करता है। "क्लिक ()" के बाद जब मैं पृष्ठ को लोड करने की उम्मीद करता हूं, तो मैं स्पष्ट रूप से रीडिस्टेट के लिए (WebDriverWait का उपयोग करके) प्रतीक्षा करता हूं। ]
रूबी कार्यान्वयन:
wait = Selenium::WebDriver::Wait.new(:timeout => 10)
wait.until {
@driver.execute_script("return document.readyState;") == "complete"
}
आप System.out
लाइन को हटा सकते हैं । यह डीबग उद्देश्यों के लिए जोड़ा गया है।
WebDriver driver_;
public void waitForPageLoad() {
Wait<WebDriver> wait = new WebDriverWait(driver_, 30);
wait.until(new Function<WebDriver, Boolean>() {
public Boolean apply(WebDriver driver) {
System.out.println("Current Window State : "
+ String.valueOf(((JavascriptExecutor) driver).executeScript("return document.readyState")));
return String
.valueOf(((JavascriptExecutor) driver).executeScript("return document.readyState"))
.equals("complete");
}
});
}
ये सभी समाधान विशिष्ट मामलों के लिए ठीक हैं, लेकिन वे कुछ संभावित समस्याओं में से कम से कम एक से पीड़ित हैं:
वे पर्याप्त सामान्य नहीं हैं - वे चाहते हैं कि आप समय से पहले जानना चाहते हैं कि कुछ विशिष्ट स्थिति आपके द्वारा लिए जा रहे पृष्ठ के लिए सही होगी (जैसे कुछ तत्व प्रदर्शित किया जाएगा)
वे एक दौड़ की स्थिति के लिए खुले हैं जहां आप एक ऐसे तत्व का उपयोग करते हैं जो वास्तव में पुराने पृष्ठ के साथ-साथ नए पृष्ठ पर भी मौजूद है।
यहाँ एक सामान्य समाधान पर मेरा प्रयास है जो इस समस्या से बचा जाता है (पायथन में):
सबसे पहले, एक सामान्य "प्रतीक्षा" फ़ंक्शन (यदि आप चाहें तो WebDriverWait का उपयोग करें, मैं उन्हें बदसूरत लगता हूं):
def wait_for(condition_function):
start_time = time.time()
while time.time() < start_time + 3:
if condition_function():
return True
else:
time.sleep(0.1)
raise Exception('Timeout waiting for {}'.format(condition_function.__name__))
इसके बाद, समाधान इस तथ्य पर निर्भर करता है कि सेलेनियम शीर्ष स्तर के <html>
तत्व सहित एक पृष्ठ पर सभी तत्वों के लिए एक (आंतरिक) आईडी-संख्या रिकॉर्ड करता है । जब कोई पेज रिफ्रेश या लोड होता है, तो उसे नई आईडी के साथ एक नया html एलिमेंट मिलता है।
इसलिए, यह मानते हुए कि आप उदाहरण के लिए टेक्स्ट "माई लिंक" के लिंक पर क्लिक करना चाहते हैं:
old_page = browser.find_element_by_tag_name('html')
browser.find_element_by_link_text('my link').click()
def page_has_loaded():
new_page = browser.find_element_by_tag_name('html')
return new_page.id != old_page.id
wait_for(page_has_loaded)
अधिक पायथोनिक, पुन: प्रयोज्य, सामान्य सहायक के लिए, आप एक संदर्भ प्रबंधक बना सकते हैं:
from contextlib import contextmanager
@contextmanager
def wait_for_page_load(browser):
old_page = browser.find_element_by_tag_name('html')
yield
def page_has_loaded():
new_page = browser.find_element_by_tag_name('html')
return new_page.id != old_page.id
wait_for(page_has_loaded)
और फिर आप इसे किसी भी सेलेनियम बातचीत पर उपयोग कर सकते हैं:
with wait_for_page_load(browser):
browser.find_element_by_link_text('my link').click()
मुझे लगता है कि बुलेटप्रूफ है! तुम क्या सोचते हो?
इसके बारे में एक ब्लॉग पोस्ट में अधिक जानकारी यहाँ
आप कक्षा का उपयोग भी ExpectedConditions
कर सकते हैं: किसी भी कार्य को आगे की कार्रवाई करने से पहले वेबपृष्ठ पर दिखाने के लिए किसी तत्व के लिए स्पष्ट रूप से प्रतीक्षा करें
ExpectedConditions
यदि तत्व दिखाई दे रहा है, तो यह निर्धारित करने के लिए आप कक्षा का उपयोग कर सकते हैं :
WebElement element = (new WebDriverWait(getDriver(), 10)).until(ExpectedConditions.visibilityOfElementLocated(By.cssSelector("input#houseName")));
ExpectedConditions class Javadoc
उन सभी स्थितियों की सूची देखें जिन्हें आप जांचने में सक्षम हैं।
यह वेबड्राइवर की एक गंभीर सीमा लगती है। स्पष्ट रूप से एक तत्व की प्रतीक्षा करने से पृष्ठ लोड होने का अर्थ नहीं होगा, विशेष रूप से DOM को पूरी तरह से (पहले से ही राज्य) बनाया जा सकता है जिससे JS अभी भी निष्पादित हो रहा है और CSS और छवियां अभी भी लोड हो रही हैं।
मेरा मानना है कि सब कुछ शुरू होने के बाद सबसे सरल समाधान जेएस वेरिएबल को ऑनलोड घटना पर सेट करना है और सेलेनियम में इस जेएस वेरिएबल की प्रतीक्षा करें।
यदि आप किसी विशिष्ट तत्व को लोड करने के लिए इंतजार करना चाहते हैं, तो आप isDisplayed()
विधि का उपयोग कर सकते हैं RenderedWebElement
:
// Sleep until the div we want is visible or 5 seconds is over
long end = System.currentTimeMillis() + 5000;
while (System.currentTimeMillis() < end) {
// Browsers which render content (such as Firefox and IE) return "RenderedWebElements"
RenderedWebElement resultsDiv = (RenderedWebElement) driver.findElement(By.className("gac_m"));
// If results have been returned, the results are displayed in a drop down.
if (resultsDiv.isDisplayed()) {
break;
}
}
( 5 मिनट से शुरू होने वाली गाइड का उदाहरण )
RenderedWebElement
एपीआई में नहीं है। हालाँकि, isDisplayed()
विधि अब सीधे उपलब्ध है WebElement
।
इस प्रतीक्षा में स्पष्ट रूप से प्रतीक्षा या सशर्त प्रतीक्षा करें जब तक कि यह शर्त न दी जाए।
WebDriverWait wait = new WebDriverWait(wb, 60);
wait.until(ExpectedConditions.elementToBeClickable(By.name("value")));
यह 60 सेकंड के लिए प्रत्येक वेब तत्व की प्रतीक्षा करेगा।
उस समय तक पृष्ठ पर प्रत्येक तत्व की प्रतीक्षा के लिए अनुमानित प्रतीक्षा का उपयोग करें।
driver.manage().timeouts().implicitlyWait(60, TimeUnit.SECONDS);
यह 60 सेकंड के लिए प्रत्येक वेब तत्व की प्रतीक्षा करेगा।
दिए गए समय तक पृष्ठ पर प्रत्येक तत्व की प्रतीक्षा के लिए अनुमानित प्रतीक्षा का उपयोग करें।
driver.manage().timeouts().implicitlyWait(30, TimeUnit.SECONDS);
यह 30 सेकंड के लिए पृष्ठ पर हर तत्व की प्रतीक्षा करता है।
एक और प्रतीक्षा स्पष्ट रूप से इस प्रतीक्षा में सशर्त प्रतीक्षा या सशर्त प्रतीक्षा है जब तक कि दी गई स्थिति नहीं है।
WebDriverWait wait = new WebDriverWait(driver, 40);
WebElement element = wait.until(ExpectedConditions.elementToBeClickable(By.id("someid")));
आईडी में स्टेटिक एलिमेंट आईडी देते हैं, जो पेज पर लोड होते ही प्रदर्शित होता है।
मुझे आश्चर्य है कि आम तौर पर आप पहली पसंद नहीं थे क्योंकि आप आमतौर पर जानते हैं कि आप उस पृष्ठ पर किस तत्व के साथ बातचीत करेंगे जिसे आप लोड करने की प्रतीक्षा कर रहे हैं। मेरा दृष्टिकोण हमेशा विधेयकों / कार्यों जैसे / waitForElementByID(String id)
और waitForElemetVisibleByClass(String className)
आदि का निर्माण करने के लिए रहा है और फिर इनका उपयोग और पुन: उपयोग करें जहाँ भी मुझे उनकी आवश्यकता है, यह एक पृष्ठ लोड या पृष्ठ सामग्री परिवर्तन के लिए हो, जिसका मैं इंतजार कर रहा हूं।
उदाहरण के लिए,
मेरी परीक्षा कक्षा में:
driverWait.until(textIsPresent("expectedText");
मेरे टेस्ट क्लास पैरेंट में:
protected Predicate<WebDriver> textIsPresent(String text){
final String t = text;
return new Predicate<WebDriver>(){
public boolean apply(WebDriver driver){
return isTextPresent(t);
}
};
}
protected boolean isTextPresent(String text){
return driver.getPageSource().contains(text);
}
हालांकि यह बहुत कुछ लगता है, यह आपके लिए बार-बार जाँच का ध्यान रखता है और समय-समय पर अंतिम प्रतीक्षा समय के साथ कितनी बार जाँच की जा सकती है इसके लिए अंतराल। इसके अलावा, आप इस तरह के तरीकों का पुन: उपयोग करेंगे।
इस उदाहरण में, मूल वर्ग को परिभाषित किया और आरंभ WebDriver driver
किया WebDriverWait driverWait
।
आशा है कि ये आपकी मदद करेगा।
वेबड्राइवर के लिए जावा बाइंडिंग का उपयोग करते समय पेज लोड के लिए इंतजार करने का सबसे अच्छा तरीका पेजएक्टीविटी के साथ पेज ऑब्जेक्ट डिज़ाइन पैटर्न का उपयोग करना है। यह आपको इसका उपयोग करने की अनुमति देता है AjaxElementLocatorFactory
जो इसे डालने के लिए बस आपके सभी तत्वों के लिए एक वैश्विक प्रतीक्षा के रूप में कार्य करता है। इसमें ड्रॉप-बॉक्स या जटिल जावास्क्रिप्ट संक्रमण जैसे तत्वों की सीमाएं हैं, लेकिन यह आवश्यक कोड की मात्रा को काफी कम कर देगा और परीक्षण समय को गति देगा। इस ब्लॉगपोस्ट में एक अच्छा उदाहरण पाया जा सकता है। कोर जावा की बुनियादी समझ है।
http://startingwithseleniumwebdriver.blogspot.ro/2015/02/wait-in-page-factory.html
NodeJS समाधान:
में NodeJS आप इसे वादों के माध्यम से प्राप्त कर सकते हैं ...
यदि आप इस कोड को लिखते हैं, तो आप यह सुनिश्चित कर सकते हैं कि पेज पूरी तरह से लोड हो जाता है जब आप उस समय प्राप्त करते हैं ...
driver.get('www.sidanmor.com').then(()=> {
// here the page is fully loaded!!!
// do your stuff...
}).catch(console.log.bind(console));
यदि आप यह कोड लिखते हैं, तो आप नेविगेट करेंगे, और सेलेनियम 3 सेकंड प्रतीक्षा करेगा ...
driver.get('www.sidanmor.com');
driver.sleep(3000);
// you can't be sure that the page is fully loaded!!!
// do your stuff... hope it will be OK...
सेलेनियम प्रलेखन से:
this.get (url) → तबेबल
शेड्यूल दिए गए URL पर नेविगेट करने के लिए एक कमांड है।
एक वादा लौटाता है जिसे तब हल किया जाएगा जब दस्तावेज़ ने लोड करना समाप्त कर दिया हो ।
यहाँ एक जावा 8 संस्करण है जो वर्तमान में सबसे अधिक उत्तर दिया गया है :
WebDriverWait wait = new WebDriverWait(myDriver, 15);
wait.until(webDriver -> ((JavascriptExecutor) myDriver).executeScript("return document.readyState").toString().equals("complete"));
जहां myDriver
एक WebDriver
वस्तु (पहले घोषित) है।
नोट : ध्यान रखें कि यह विधि ( document.readyState
) केवल DOM की जाँच करती है।
अपनी स्क्रिप्ट में फ़ंक्शन के नीचे कॉल करें, यह तब तक इंतजार करेगा जब तक जावास्क्रिप्ट का उपयोग करके पृष्ठ लोड नहीं किया जाता है
public static boolean isloadComplete(WebDriver driver)
{
return ((JavascriptExecutor) driver).executeScript("return document.readyState").equals("loaded")
|| ((JavascriptExecutor) driver).executeScript("return document.readyState").equals("complete");
}
/**
* Call this method before an event that will change the page.
*/
private void beforePageLoad() {
JavascriptExecutor js = (JavascriptExecutor) driver;
js.executeScript("document.mpPageReloaded='notYet';");
}
/**
* Call this method after an event that will change the page.
*
* @see #beforePageLoad
*
* Waits for the previous page to disappear.
*/
private void afterPageLoad() throws Exception {
(new WebDriverWait(driver, 10)).until(new Predicate<WebDriver>() {
@Override
public boolean apply(WebDriver driver) {
JavascriptExecutor js = (JavascriptExecutor) driver;
Object obj = js.executeScript("return document.mpPageReloaded;");
if (obj == null) {
return true;
}
String str = (String) obj;
if (!str.equals("notYet")) {
return true;
}
return false;
}
});
}
आप दस्तावेज़ से एक तत्व में बदल सकते हैं, उस स्थिति में जहां दस्तावेज़ का केवल एक हिस्सा बदला जा रहा है।
यह तकनीक तब से जवाब से प्रेरित थी।
सेलेनियमवाटर :
import com.google.common.base.Function;
import org.openqa.selenium.By;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.WebElement;
import org.openqa.selenium.support.ui.WebDriverWait;
public class SeleniumWaiter {
private WebDriver driver;
public SeleniumWaiter(WebDriver driver) {
this.driver = driver;
}
public WebElement waitForMe(By locatorname, int timeout){
WebDriverWait wait = new WebDriverWait(driver, timeout);
return wait.until(SeleniumWaiter.presenceOfElementLocated(locatorname));
}
public static Function<WebDriver, WebElement> presenceOfElementLocated(final By locator) {
// TODO Auto-generated method stub
return new Function<WebDriver, WebElement>() {
@Override
public WebElement apply(WebDriver driver) {
return driver.findElement(locator);
}
};
}
}
और आप इसका उपयोग करते हैं :
_waiter = new SeleniumWaiter(_driver);
try {
_waiter.waitForMe(By.xpath("//..."), 10);
}
catch (Exception e) {
// Error
}
आप नीचे दिए गए मौजूदा तरीके का उपयोग कर सकते हैं कि पेजेजलडाईटाउट के लिए समय निर्धारित करें नीचे दिए गए उदाहरण में यदि पृष्ठ को लोड होने में 20 सेकंड से अधिक समय लग रहा है, तो यह पेज रीलोड के अपवाद को फेंक देगा
WebDriver driver = new FirefoxDriver();
driver.manage().timeouts().pageLoadTimeout(20, TimeUnit.SECONDS)
वेबपृष्ठ पर किसी तत्व को दिखाने के लिए आप स्पष्ट रूप से प्रतीक्षा कर सकते हैं, इससे पहले कि आप कोई कार्रवाई कर सकें (जैसे element.click ())
driver.get("http://somedomain/url_that_delays_loading");
WebElement myDynamicElement = (new WebDriverWait(driver, 10))
.until(new ExpectedCondition<WebElement>(){
@Override
public WebElement apply(WebDriver d) {
return d.findElement(By.id("myDynamicElement"));
}});
यह वही है जो मैंने एक समान परिदृश्य के लिए इस्तेमाल किया और यह ठीक काम करता है।
मैंने जो सबसे अच्छा तरीका देखा है, उसका उपयोग करना है stalenessOf
ExpectedCondition करना है, पुराने पेज के बासी होने का इंतजार करना है।
उदाहरण:
WebDriver driver = new FirefoxDriver();
WebDriverWait wait = new WebDriverWait(driver, 10);
WebElement oldHtml = driver.findElement(By.tagName("html"));
wait.until(ExpectedConditions.stalenessOf(oldHtml));
यह पुराने HTML टैग के बासी होने के लिए दस सेकंड तक प्रतीक्षा करेगा, और यदि ऐसा नहीं होता है तो एक अपवाद फेंक दें।
मैं नोड + सेलेनियम-वेबड्राइवर का उपयोग करता हूं (जो संस्करण अब 3.5.0 है)। मैं इसके लिए क्या करता हूं:
var webdriver = require('selenium-webdriver'),
driver = new webdriver.Builder().forBrowser('chrome').build();
;
driver.wait(driver.executeScript("return document.readyState").then(state => {
return state === 'complete';
}))
आप प्रतीक्षा का उपयोग कर सकते हैं। सेलेनियम में मूल रूप से प्रतीक्षा के 2 प्रकार हैं
- अधूरा इंतजार
यह बहुत सरल है कृपया नीचे सिंटैक्स देखें:
driver.manage().timeouts().implicitlyWait(20, TimeUnit.SECONDS);
- स्पष्ट प्रतीक्षा करें
इस प्रतीक्षा में स्पष्ट रूप से प्रतीक्षा या सशर्त प्रतीक्षा करें जब तक कि दी गई स्थिति उत्पन्न न हो जाए।
WebDriverWait wait = new WebDriverWait(driver, 40);
WebElement element = wait.until(ExpectedConditions.elementToBeClickable(By.id("someid")));
आप अन्य गुणों का उपयोग कर सकते हैं जैसे visblityOf()
,visblityOfElement()
यदि कोई सेलेनाइड का उपयोग करता है:
public static final Long SHORT_WAIT = 5000L; // 5 seconds
$("some_css_selector").waitUntil(Condition.appear, SHORT_WAIT);
अधिक शर्तें यहां पाई जा सकती हैं: http://selenide.org/javadoc/3.0/com/codeborne/selenide/Condition.html
मेरे मामले में, मैंने पेज लोड की स्थिति जानने के लिए निम्नलिखित का उपयोग किया। हमारे आवेदन में लोडिंग जिफ़ (एस) मौजूद हैं और, मैं उन्हें स्क्रिप्ट में अवांछित प्रतीक्षा समय को समाप्त करने के लिए निम्नानुसार सुनता हूं।
public static void processing(){
WebDriverWait wait = new WebDriverWait(driver, 30);
wait.until(ExpectedConditions.visibilityOfElementLocated(By.xpath("//div[@id='Msgpanel']/div/div/img")));
wait.until(ExpectedConditions.invisibilityOfElementLocated(By.xpath("//div[@id='Msgpanel']/div/div/img")));
}
जहाँ xpath HTML DOM में gif का पता लगाता है। इसके बाद, आप अपनी कार्रवाई के तरीकों को भी लागू कर सकते हैं क्लिक करें।
public static void click(WebElement elementToBeClicked){
WebDriverWait wait = new WebDriverWait(driver, 45);
wait.until(ExpectedConditions.visibilityOf(element));
wait.until(ExpectedConditions.elementToBeClickable(element));
wait.ignoring(NoSuchElementException.class).ignoring(StaleElementReferenceException.class); elementToBeClicked.click();
}
इन सभी उत्तरों के लिए मनुष्य को बहुत अधिक कोड की आवश्यकता होती है। यह एक बहुत ही साधारण चीज होनी चाहिए।
सिर्फ वेबड्राइवर और जाँच के साथ कुछ सरल जावास्क्रिप्ट क्यों नहीं इंजेक्ट करें। यह मैं अपने webscraper वर्ग में उपयोग की जाने वाली विधि है। जावास्क्रिप्ट बहुत ही बुनियादी है भले ही आप js नहीं जानते हों।
def js_get_page_state(self):
"""
Javascript for getting document.readyState
:return: Pages state.
More Info: https://developer.mozilla.org/en-US/docs/Web/API/Document/readyState
"""
ready_state = self.driver.execute_script('return document.readyState')
if ready_state == 'loading':
self.logger.info("Loading Page...")
elif ready_state == 'interactive':
self.logger.info("Page is interactive")
elif ready_state == 'complete':
self.logger.info("The page is fully loaded!")
return ready_state
एक क्लिक के बाद पृष्ठ लोड के लिए प्रतीक्षा करने के लिए सेलेनियम कैसे प्राप्त करें निम्नलिखित दिलचस्प दृष्टिकोण प्रदान करता है:
WebElement
पुराने पृष्ठ से एक संदर्भ संग्रहीत करें ।WebElement
जब तक StaleElementReferenceException
फेंका नहीं जाता तब तक ऑपरेशन जारी रखें ।नमूना कोड:
WebElement link = ...;
link.click();
new WebDriverWait(webDriver, timeout).until((org.openqa.selenium.WebDriver input) ->
{
try
{
link.isDisplayed();
return false;
}
catch (StaleElementReferenceException unused)
{
return true;
}
});
new WebDriverWait(driver, 10).until(ExpectedConditions.stalenessOf(element))
।