web-dev-qa-db-ja.com

Selenium-古い要素参照:要素はページに添付されていません

ウェブサイトから取得したアイテムを表示しようとしているときにエラーが発生する理由を理解しようとしています。また、ブラウザにはgoogle chromeを使用しています。

chromeDriver.Navigate().GoToUrl("somewebsites");

chromeDriver.FindElement(By.Id("something.link.text")).Click();
chromeDriver.Manage().Timeouts().ImplicitlyWait(TimeSpan.FromSeconds(5));

そして、私のコードの他の部分

var item = chromeDriver.FindElementsByXPath("//*[starts-with(@id,\"g_1_\")]/td[3]/span");
foreach (var value in item)
{
    Console.WriteLine(value.Text); 
}

chromeDriver.FindElement(By.Id( "something.link.text"))。Click();」を使用すると、エラーが発生します。プルしたデータを表示できません。

エラーメッセージでは、「OpenQA.Selenium.StaleElementReferenceException: 'stale element reference:element is not attach to the page document "」と表示されます。他の投稿をチェックしましたが、わかりませんでした。どうすれば解決できますか?

私が読んだように、SeleniumはWebサイトを開く時間よりもはるかに高速に応答するため、エラーが発生します。また、まれに、Seleniumを要素に配置できないことがあります。なにか提案を?

編集:表示機能から「。text」を削除すると、「OpenQA.Selenium.Remote.RemoteWebElement」と表示されます。文字列の問題はありますか?

EDIT2:次のように、Webサイトから取得したデータを保持できます。

[i] = "System.Collections.ObjectModel.ReadOnlyCollection`1 [OpenQA.Selenium.IWebElement]"このために、私は次のように書きました。

string[] test= new string[100];

for (int i = 0; i < 100; i++)
{
     kaan[i] = driver.FindElements(By.XPath("//*[starts-with(@id,\"g_1_\")]/td[3]/span")).ToString();
}

どのようにテキストに変換できますか

10

私はc#で働いていませんが、Java/Seleniumで働いています。しかし、私はあなたに古さを克服するためのアイデアを与えることができます。

一般に、webelementの開始後に要素の属性または何かが変更された場合、Stale例外が発生します。たとえば、ユーザーが同じページ上の同じ要素をクリックしたが、ページの更新後にstaleelement例外が発生する場合があります。

これを克服するために、ページが変更または更新された場合に備えて、新しいWeb要素を作成できます。以下のコードでいくつかのアイデアを得ることができます。(Javaにありますが、概念は同じです)

例:

 webElement element = driver.findElement(by.xpath("//*[@id='StackOverflow']"));
 element.click();
 //page is refreshed
 element.click();//This will obviously throw stale exception

これを克服するために、xpathを何らかの文字列に保存し、それを使用して新しいWeb要素を作成できます。

String xpath = "//*[@id='StackOverflow']";
driver.findElement(by.xpath(xpath)).click();
//page has been refreshed. Now create a new element and work on it
driver.fineElement(by.xpath(xpath)).click();   //This works

この場合、ウェブ要素のグループを収集し、テキストを取得するために繰り返します。しかし、webelementを収集した後にwebelementにいくつかの変更があり、gettextが古くなっているようです。ループを使用して、外出先で要素を作成し、テキストを取得できます。

for(int i = 0; i<5; i++)
{
   String value = driver.findElement(by.xpath("//.....["+i+"]")).getText);
   System.out.println(value);
}

これがお役に立てば幸いです。ありがとう。

8
santhosh kumar

このタイプのエラーは通常、更新されたDOMが原因です。 javascript/ajax呼び出しを含むすべてのページで、実際にそれらの呼び出しが完了するのを待ってからサイトと対話することをお勧めします。通常、この待機は、ページが読み込まれた直後、およびjavascript/ajax呼び出しやDOMの更新をトリガーする何らかの種類のアクションを実行するときに実行します。実際には、これは、ページがロードされた(または対話された)後に以下の関数を実行し、その後、対話したい要素を見つけることを意味します。

public void WaitForJqueryAjax() {
        int delay = MaxdelaySeconds;
        while(delay > 0) {
            Thread.Sleep(1000);
            var jquery = (bool)(this.driver as IJavaScriptExecutor)
                .ExecuteScript("return window.jQuery == undefined");
            if(jquery) {
                break;
            }
            var ajaxIsComplete = (bool)(this.driver as IJavaScriptExecutor)
                .ExecuteScript("return window.jQuery.active == 0");
            if(ajaxIsComplete) {
                break;
            }
            delay--;
        }
    }
2
Agent Shoulder

最初はこの問題がありましたが、いくつかのトリックで解決しました

  • 一部の親要素がページに表示されるのを待ちます(親コンテナdivの場合があります)
  • 使用しようとしている要素の周りで完了するajax(xhr)リクエストの待機
  • (これはトリックです)インスタンスプロパティ値として要素を保存せず、常に要求時にフェッチします(これは、staleelementから役立ちます)。 C#6、プライベートIWebElementの例_parentContainer => _driver.FindElement(...)

また、IWebElementの抽象basecontrolといくつかの拡張メソッドを作成し、要素を見つけながら基本的なチェック操作を行うことができます。

0
Peter