2

Internet Explorer で、もともと Chrome に対して開発された (そしてそこでうまく機能する) いくつかのスクリプトを試してみたところ、StaleElementReferenceExceptions が標準のように見えることがわかりました。どうやらこれは IE が非常に遅いためでしょうか?

これらの例外は、WebElement を見つけて DOM が変更されたときに発生し、その WebElement に対して何かを実行しようとすると、ページが変更され、WebElement 内の参照が無効になったため、Selenium が混乱することを理解しています。それが StaleElementReferenceExceptions が発生する理由である場合、なぜこれが表示されるのかわかりません。

Flash Player を含む新しいウィンドウがあり、Flash Player がビデオを再生した後、オブジェクトからいくつかのパラメーターを取得しようとしました。ページのソースは次のようになります。

<object id="flashContent" width="100%" height="100%" type="application/x-shockwave-flash" name="flashContent" data="[redacted]" style="visibility: visible;">
    <param name="scale" value="noscale">
    <param name="wmode" value="opaque">
    <param name="allowfullscreen" value="true">
    <param name="allowscriptaccess" value="always">
    <param name="bgcolor" value="">
    <param name="SeamlessTabbing" value="false">
    <param name="flashvars" value="[redacted]">
</object>

flashvars パラメータの値を読み取ることに興味があるので、次のコードを用意しました。

text = driver.findElement(By.cssSelector("object#flashContent param[name='flashvars']")).getAttribute("value");

したがって、param WebElement を見つけてからその属性を取得するまでの時間を短縮することはできないようですが、getAttribute は毎回 StaleElementReferenceException をスローしています。ページのソースを開いてウィンドウを見ましたが、私が見る限り、何も変わっていません。一定期間例外をキャッチしようとしましたが、DOM が静かで WebElement が安定している時間に到達することを期待して再試行しましたが、次のコードはまったく役に立ちませんでした。

    timer.start();
    while (true) {
        try {
            text = getDriver().findElement(By.cssSelector("object#flashContent param[name='flashvars']"))
                    .getAttribute("value");
            break;
        } catch (StaleElementReferenceException e) {
            if (timer.getElapsedSeconds() >= 20) {
                debug("getAttribute is borked, throwing up...");
                throw e;
            } else {
                debug("getAttribute failed again but we're still trying after " + timer.getElapsedMilliseconds() + " milliseconds.");
            }
        }
    }

上記は、StaleElementReferenceException がスローされた場合でも、findElement 呼び出しが通常タイムアウトになるまで (20 秒の暗黙のタイムアウト)、find/getAttribute コンボを試行し続けるように設計されています。これを実行した結果、findElement 呼び出しが成功し、getAttribute 呼び出しが 50 ミリ秒ごとに約 20 秒間 StaleElementReferenceException をスローしました。それからそれは捨てられました。この間、ページ上で何も起こっていませんでした。少なくとも、私が見ることはできませんでした。

このような状況で WebElement が古くなっている理由や方法についてのアイデアはありますか?

編集:ページからのみデータを取得しようとしている状況 (つまり、クリックまたはキーストロークの送信ではなく、ページから属性またはテキストを取得する) にのみ適用される回避策を見つけました。私のコードはすでにJSoupというライブラリを使用して DOM をメモリに読み込みます。これは、DOM をナビゲートして情報を検索する必要があるが、DOM 自体でパフォーマンスの低い一連の Selenium 検索操作を回避したい場合に非常に便利です。JSoup を使用することで、DOM の静的バージョンを読み取り、求めていた情報を抽出することができました。ただし、キーをクリックしたり送信したりしたい状況に陥った場合、この回避策は役に立たないので、他のオプションがあるかどうかを知りたい.

4

1 に答える 1

0

StaleElementReferenceException は、コードが DOM に存在しなくなったコンテンツを見つけようとしたために発生しています。JSoup を使用して古い静的バージョンの DOM にアクセスしている場合、Flash ビデオが終了した後の DOM のコンテンツには、flashvars パラメータやその value 属性が含まれていない可能性があります。最速のコード オプションを使用した最初のアプローチは正しいです。

  String text = driver.findElement(By.cssSelector("object#flashContentparam[name='flashvars']")).getAttribute("value");

ビデオが終了した後、ビデオが終了したことを示す要素が DOM に存在するのを待ってから、flashvars パラメータとその value 属性を見つけようとします。PS: StaleElementReferenceException が急速な完全または部分 (AJAX) ページの更新 (<500 ミリ秒) によって引き起こされることはめったにありません。通常、これはアルゴリズムの問​​題です。

于 2015-07-01T21:40:09.420 に答える