「要素はクリックできません」エラーのデバッグ


397

これはChromeでのみ表示されます。

完全なエラーメッセージは次のとおりです。

「org.openqa.selenium.WebDriverException:要素はポイント(411、675)ではクリックできません。他の要素はクリックを受け取ります:...」

「クリックを受け取る」要素は、問題の要素の横にあり、その上ではなく、重なっておらず、ページ内を移動していません。

オフセットを追加しようとしましたが、それも機能しません。アイテムは表示されたウィンドウ上にあり、スクロールする必要はありません。


2
ページが読み込まれるのを待ちますか?おそらく、ページの読み込み中に他の要素が重複していますか?
ヒーローキラー2012

55
到着したばかりの人のための短い話-要素はページに表示されないため、クリックできません。ウィンドウをスクロールしてビューポートをスクロールする必要がありますwindow.ScrollTo。
クリスB.ベーレンス14

67
@ ChrisB.Behrensこれは常に当てはまるとは限りません。この特定のエラーは、要素が別の要素で覆われている場合にも発生する可能性があります。位置が固定された別の要素であるボタンをクリックしようとすると、この例外が発生しました。
マーティンキャシディ

4
Chromedriverだけでなく、Firefoxにも同じ問題がありました。上記の他の人が示唆したように、ページが完全に再読み込みされるまで待機する遅延を実装することで問題を修正しました。
codervince 2016年

5
これは、scrollToを発行したり、待機したりするための絶対に間違ったアドバイスだと思います。セレンクリックのアルゴリズムのように見えます:1.要素の位置を計算します2.この位置にスクロールします(自分で発行する必要はありません)。実際のクリックイベント送信の直前の位置)私のアドバイスは次のとおりです。1.要素がビューポート内にあるかどうかを確認します。2.要素が他の要素(スティッキメニューなど)で覆われているかどうかを確認し、要素がある場合は非表示にするか、組み込みのscrollToに依存せずにクリックする前に手動でスクロールします。
Vitalik Verhovodov 2016年

回答:


325

これは、次の3つのタイプが原因です。

1.要素はクリックしても見えません。

クリックさせるには、ActionsまたはJavascriptExecutorを使用します。

アクション別:

WebElement element = driver.findElement(By("element_path"));

Actions actions = new Actions(driver);

actions.moveToElement(element).click().perform();

JavascriptExecutorによって:

JavascriptExecutor jse = (JavascriptExecutor)driver;

jse.executeScript("scroll(250, 0)"); // if the element is on top.

jse.executeScript("scroll(0, 250)"); // if the element is on bottom.

または

JavascriptExecutor jse = (JavascriptExecutor)driver;

jse.executeScript("arguments[0].scrollIntoView()", Webelement); 

次に、要素をクリックします。

2.ページは要素をクリックする前に更新されます。

これを行うには、ページを数秒待つようにします。

3.要素はクリック可能ですが、その上にスピナー/オーバーレイがあります

以下のコードは、オーバーレイが消えるまで待機します

By loadingImage = By.id("loading image ID");

WebDriverWait wait = new WebDriverWait(driver, timeOutInSeconds);

wait.until(ExpectedConditions.invisibilityOfElementLocated(loadingImage));

次に、要素をクリックします。


52
原因の3つ目のタイプがあります。これは、要素がdivまたはspanでラップされていることです。ページは完全に読み込まれ、ビューポート内に完全に読み込まれますが、Chromedriverはクリックを拒否します。FFとIEのwebdriverは問題ありません。実際の人間には、スパンが存在するという手掛かりはなく、ブラウザは人間として実際にクリックしても気になりません。動き回ったり、待ったりしても、この問題は解決されません。ケース3では、Chrome / chromedriverを回避するか、ページのHTMLを書き直すことが唯一の選択肢のようです
Don Simon

54
@DonSimon私はあなたがしたのと同じ問題がありました。.Clickの代わりに.SendKeys(Keys.Return)を使用することで回避できました。これは、この問題が発生していたChromeと、この特定のリンク(Divにラップされたアンカー)で別の同様の問題が発生していたFirefoxで機能しました。
Peter Bernier、2015

17
@PeterBernierによって提案されたソリューションは、要素がdivまたはspanでラップされている場合にうまく機能します。Pythonでは、.send_keys( '\ n')を使用してクリックをシミュレートし、Chromeの問題を回避しました。
GJ

4
要素がdiv要素によって非表示になっている場合、次のコードで修正されます。executeJavascript( "arguments [0] .click();"、selenium.findElement(locator));
EsotericNonsense

要素がクリック可能になるまで待つこともできます。wait.Until(ExpectedConditions.ElementToBeClickable(webElement));
Chielus、2016年

67

また、JavaScriptクリックを使用することもでき、スクロールは必要ありません。

IJavaScriptExecutor ex = (IJavaScriptExecutor)Driver;
ex.ExecuteScript("arguments[0].click();", elementToClick);

5
信じられない!isDisplayed()とisEnabled()が要素をクリックするのに十分でない条件がある場合、セレンが提供するclick()メソッドを破棄しないのはなぜですか?これが唯一の解決策のようです。ありがとう!
Giovanniビットライナー2017

2
+1:これは私のために働いたソリューションです。actions.MoveToElementC#では私のために機能しませんでした。他のスクロールソリューションは、スクロールによって要素が正しく表示されなかったり、ページ上の要素の位置が変わったりする可能性があるため、少し壊れやすいように見えました。
ユーザー

1
このソリューションは、要素が表示されていないがページに存在する場合に最も簡単です
Yashveer Rana

@Giovanni Bitliner実際のユーザーシナリオではないため、この方法は提供されていません。ユーザーは、ローダーが消えるまで待つ必要もあります。セレンについては素晴らしいことだと思います。
Gideon Mulder

+1また私のために働いた。コードにflwgメソッドを追加したところです。`private void jsClick(IWebElement element、IWebDriver driver){IJavaScriptExecutor ex =(IJavaScriptExecutor)driver; ex.ExecuteScript( "arguments [0] .click();"、element); } `この方法で呼び出されました: 'jsClick(driver.FindElement(By.XPath(" xpathOfTheElement "))); `
エレミア2017年

46

そのためのchromedriverにバグがあるようです(問題は修正できないとマークされていることです)-> GitHubリンク

(おそらくFreedomSponsorsに賞金をかけますか?)

コメント#27で回避策が提案されています。多分それはあなたのために働くでしょう-


4
公平に見える-ボタンが画面上にない場合、実際にはクリック可能ではありません。
Evan Knowles

これはバグではありません。これは意図された動作であり、正しいものです。他の提案のとおり、要素がビューポートの外にある場合は、それにスクロールする必要があります。
Alex Skrypnyk 2015年

Firefoxを試してみたところ、このエラーが発生しないことがわかりましたが、クリックはまだ無視されていました。親divの高さがゼロであることが判明しました。それが修正されると、両方とも正常に動作しました。
dansalmo 2017年

35

私は同じ問題を抱えており、提供されたすべての解決策を試しましたが、それらは私にとってはうまくいきませんでした。最終的に私はこれを使いました:

JavascriptExecutor js = (JavascriptExecutor) driver;
js.executeScript("var evt = document.createEvent('MouseEvents');" + "evt.initMouseEvent('click',true, true, window, 0, 0, 0, 0, 0, false, false, false, false, 0,null);" + "arguments[0].dispatchEvent(evt);", findElement(element));

お役に立てれば


16

これは、セレン駆動のChromeウィンドウが小さすぎて開かれた状況で見られました。クリックされる要素はビューポートの外にあるため、失敗しました。

それは論理的に聞こえます...実際のユーザーはウィンドウのサイズを変更するかスクロールして、要素を表示して実際にクリックする必要があります。

セレンドライバーにウィンドウサイズを適切に設定するように指示した後、この問題は解消されました。webdriver APIについては、こちらで説明しています


15

うわー、ここでたくさんの答え、そして多くの良い答えがあります。

私の経験からこれに何か追加したいと思います。

ええと、私の場合、時々要素を隠すクッキーオーバーレイがありました。要素までスクロールしても機能します。しかし、私の考えでは(私の場合、万能薬ではありません)、最も簡単な解決策は、全画面表示にすることです(画面ウィンドウの3/4でスクリプトを実行していました)。だからここに行きます:

driver.manage().window().maximize();

お役に立てば幸いです。


13

ruby / watir-webdriver / chrome

私は次のトリックを使用していますが、うまくいくようです:

#scroll to myelement
@browser.execute_script "window.scrollTo(#{myelement.element.wd.location[0]},#{myelement.element.wd.location[1]})"

# click myelement
myelement.when_present.fire_event("click")

1
私が見ていた問題はエリアマップでした。エラーは元の投稿と同じでした-クリックする必要がある領域の「前」のdiv。これはAJAX /タイミング/ページの読み込みの問題ではなく、領域は完全に表示されていました-フォーカスするためにスクロールすることさえできませんでした。ただし、クリックメソッドをobject.clickからobject.fire_event( "click")に変更すると、問題が解決したようです。Firefoxが正常にクリックする方法に影響を及ぼさないように、それをbegin / rescueブロックに残しました。
アダムリード

このアプローチは、ビューポートに表示されない要素があった場合の問題を回避しました。
Jason R. Coombs

13

私もこの問題に取り組みました。コードはFFで正常に動作し、Chromeでは失敗します。私がやろうとしていたのはチェックボックスをクリックすることでした。チェックボックスが表示されていない場合は、スクロールして表示してからクリックしました。Chromeではビューまでスクロールしても機能しますが、目盛りボックスの下の数ピクセルしか表示されなかったため、Webドライバーがクリックすることを拒否しました。

私の回避策はこれです:

WebElement element = _sectorPopup.findElement(...);

((Locatable) element).getCoordinates().inViewPort();
try {
    element.click();
} catch (Exception e) {
    new Actions(getWebDriver()).sendKeys(Keys.PAGE_DOWN).perform();
    element.click();
}

ChromeにはsendKeysに関する問題もあり、アクションの使用が必要になる場合があります。明らかに、あなたはあなたのマイレージが変わるかもしれないので、あなたはどちらの方向にどれだけ行く必要があるかを知る必要があります。しかし、私はこれをjavascriptハックよりも好むので、他の誰かが役に立つと思う場合に備えて、ここに投稿します。


Locatableは非推奨です。
Steve Staple 2017

12

xvfb-runでヘッドレステストを実行すると、このエラーが発生しました。彼らは完璧に地元で働いていました。chromeを使用すると、webdriver / chromedriver / chrome / javaなどのバージョンはすべて同じになります。

chromedriverの「修正されない」バグ-TonyLâmpadaが指摘したGitHubリンクは、これが画面に表示されている/表示されていないものに関連している可能性があることを示唆しています。

xvfb-runのヘルプメッセージは次のように表示されます。

-s ARGS   --server-args=ARGS    arguments (other than server number and
                                "-nolisten tcp") to pass to the Xvfb server
                                (default: "-screen 0 640x480x8")

xvfbの解像度を変更すると、エラーが解消されました。

xvfb-run -s "-screen 0 1280x1024x16" ...

9

分度器を使用するとき、これは私を助けました:

var elm = element(by.css('.your-css-class'));
browser.executeScript("arguments[0].scrollIntoView();", elm.getWebElement());
elm.click();

8

まず、最新のChromeドライバーを入手して、問題が解決するかどうかを確認してください。

私の場合、問題は解決しませんでした。しかし、これまでのところ次の解決策でうまくいきました。以下はC#コードですが、特定の言語で同じロジックに従うことができます。ここで行うことは、

ステップ1:Selenium Actionsオブジェクトを使用して要素に焦点を当て、

ステップ2:次に要素をクリックします

ステップ3:例外がある場合、Seleniumブラウザードライバーの「ExecuteScript」メソッドを介してJavaScriptスクリプトを実行することにより、要素のJavaScript「クリック」イベントをトリガーします。

ステップ1と2をスキップして、ステップ3のみを試すこともできます。ステップ3はそれ自体で機能しますが、1つのシナリオでいくつかの奇妙な動作に気づきました。このステップ3では、要素をクリックしても、要素をクリックした後、コードの他の部分で予期しない動作が発生しました。

            try
            {
                //Setup the driver and navigate to the web page...
                var driver = new ChromeDriver("folder path to the Chrome driver");
                driver.Navigate().GoToUrl("UrlToThePage");

                //Find the element...
                var element = driver.FindElement(By.Id("elementHtmlId")); 

                //Step 1
                new Actions(driver).MoveToElement(element).Perform();  

                //Step 2
                element.Click();
            }
            catch (Exception)
            {
                //Step 3
                driver.ExecuteScript("document.getElementById('elementHtmlId').click();");

            }

私も同じ問題を抱えていました。Actionsクラスを使用するステップ1はうまくいきます。私はこれについて考えたことはなかったでしょう。ありがとう!
Conner、

最初のステップは素晴らしいソリューションです。
Sovandara LENG、

7

この方法は、TonyLâmpadaの回答のコメントに基づいて作成しました。それは非常にうまく機能します。

def scroll_to(element)
  page.execute_script("window.scrollTo(#{element.native.location.x}, #{element.native.location.y})")
end

6

Pythonでセレンスクリプトを実行しているときに同じ問題が発生しました。これは、要素をクリックするために使用したものです。

from selenium.webdriver.common.action_chains import ActionChains


ActionChains(driver).click(element).perform()

5

2つのチェックボックスを次々にチェックしなければならない場合、同様の問題に直面していましたが、上記の同じエラーが発生したため、チェックボックスをチェックするためのステップの間に待機を追加しました....手順は次のとおりです。

  When I visit /administrator/user_profiles
  And I press xpath link "//*[@id='1']"
  Then I should see "Please wait for a moment..."
  When I wait for 5 seconds
  And I press xpath link "//*[@id='2']"
  Then I should see "Please wait for a moment..."
  When I visit /administrator/user_profiles_updates

これを追加するだけで、これはガーキン構文を使用する適切な方法ではありません。ステップは「与えられた-いつ-その後」の形式である必要があり、これらを混合しないでください。「then」の後にさらに「when」が必要な場合は、おそらく別のテストケースが必要です。
Floella

5

その要素にフォーカスまたはスクロールを使用する必要があります。また、明示的な待機を使用する必要がある場合もあります。

WebElement firstbutton= driver.findElement(By.xpath("Your Element"));
Actions actions = new Actions(driver);
actions.moveToElement(element);
actions.perform();

または

要素は、その上にスピナー/オーバーレイがあるためクリックできません。

By loadingImage = By.id("loading image ID");
WebDriverWait wait = new WebDriverWait(driver, timeOutInSeconds);
wait.until(ExpectedConditions.invisibilityOfElementLocated(loadingImage));

または

Point p= element.getLocation();
Actions actions = new Actions(driver);
actions.moveToElement(element).movebyoffset(p.x,p.y).click().perform();

または

それでも動作しない場合 JavascriptExecutor

JavascriptExecutor executor = (JavascriptExecutor)driver;
executor.executeScript("arguments[0].click();", firstbutton);

3

どうやらこれは、Chromeドライバーバイナリの「修正できない」バグの結果です。

私のために働いた1つの解決策(私たちのマイレージメイは異なります)は、このGoogleグループディスカッションのコメント#3にあります。

https://groups.google.com/forum/?fromgroups=#!topic/selenium-developer-activity/DsZ5wFN52tc

関連部分はここにあります:

それ以来、スパンの親アンカーのhrefに直接移動することで問題を回避しました。

driver.Navigate()。GoToUrl(driver.FindElement(By.Id(embeddedSpanIdToClick))。FindElement(By.XPath( ".."))。GetAttribute( "href"));

私の場合、Pythonを使用しているので、目的の要素を取得したら、単に

driver.get(ViewElm.get_attribute('href'))

私はこれが機能することを期待していますが、クリックしようとしている要素がリンクである場合...


3

clj-webdriver (SeleniumのClojureポート)でも同じ問題に直面していました。便宜上、前のソリューションをclojureに翻訳しました。クリックする前にこの関数を呼び出して、その問題を回避できます。

(defn scrollTo
  "Scrolls to the position of the given css selector if found"
  [q]
  (if (exists? q) 
    (let [ loc (location-once-visible q) jscript (str "window.scrollTo(" (:x loc) "," (:y loc) ")") ] 
      (execute-script jscript))))

3

これは、ドライバーがクリックしようとしているときに要素の位置が変わった場合に発生する可能性があります(IEでもこれを確認しました)。ドライバーは初期位置を保持しますが、実際にそれをクリックするまでには、その位置はその要素を指していません。ちなみに、FireFoxドライバーにはこの問題はありません。明らかに、プログラムで要素を「クリック」します。

とにかく、これは、アニメーションを使用したり、要素の高さを動的に変更したりする場合に発生します(例:)$("#foo").height(500)。高さが「落ち着いた」後にのみ要素をクリックすることを確認する必要があります。私は次のようなコードで終わりました(C#バインディング):

if (!(driver is FirefoxDriver))
{
    new WebDriverWait(driver, TimeSpan.FromSeconds(10)).Until(
        d => d.FindElement(By.Id(someDynamicDiv)).Size.Height > initialSize);
}

簡単に照会できないアニメーションやその他の要素の場合、要素が静止するのを待つ「汎用」メソッドを利用できます。

var prevLocation = new Point(Int32.MinValue, Int32.MinValue);
int stationaryCount = 0;
int desiredStationarySamples = 6; //3 seconds in total since the default interval is 500ms
return new WebDriverWait(driver, timeout).Until(d => 
{
    var e = driver.FindElement(By.Id(someId));
    if (e.Location == prevLocation)
    {
        stationaryCount++;
        return stationaryCount == desiredStationarySamples;
    }

    prevLocation = e.Location;
    stationaryCount = 0;
    return false;
});

これは私が経験しているようです。OPの「Other Element will ...」という例外が断続的に発生しますが、スクリーンショットには、モーダルが画面上にあり、要素が覆われていないことが示されています。クリックする前に待機を使用しています。私がクリックしているモーダルが開くと、実際にはページをスライドします。セレンが実際のDOMのサンプルを待機するタイミングによっては、モーダルが動いているときにモーダルをキャッチした場合に例外がスローされる可能性があります。
Levi Noecker

3

この要素の読み込みダイアログカバーが原因で、これに遭遇しました。this要素を操作する前に待機を追加することで、簡単に解決します。

try {
        Thread.sleep((int) (3000));
    } catch (InterruptedException e) {
        //
        e.printStackTrace();
    }

この助けを願っています!


3

エラーメッセージの説明

エラーメッセージは、クリックしたい要素は存在するが表示されないことを示しています。何かで覆われているか、一時的に見えない可能性があります。

テストの瞬間に要素が表示されない理由はたくさんあります。ページを再分析して、ケースに適した解決策を見つけてください。

特定の場合の解決策

私の場合、このエラーは、クリックしたばかりの画面要素のツールチップが、次にクリックしたい要素の上にポップアップ表示されたときに発生します。デフォーカスは私が必要としたソリューションでした。

  • ピントをぼかす方法の簡単な解決策は、画面の別の部分で「何もしない」応答を行う他の要素をクリックすることです。クリック操作後は何も起こりません。
  • 適切な解決策element.blur()、ツールチップをポップする要素を呼び出すことです。これにより、ツールチップが見えなくなります。

3

このエラーの原因は、クリックしようとしている要素がブラウザーのビューポート(ユーザーから見える領域)にないためです。したがって、これを克服する方法は、最初に目的の要素までスクロールしてからクリックすることです。

JavaScript:

async scrollTo (webElement) {
    await this.driver.executeScript('arguments[0].scrollIntoView(true)', webElement)
    await this.driver.executeScript('window.scrollBy(0,-150)')
}

Java:

public void scrollTo (WebElement e) {
    JavascriptExecutor js = (JavascriptExecutor) driver; 
    js.executeAsyncScript('arguments[0].scrollIntoView(true)', e)
    js.executeAsyncScript('window.scrollBy(0,-150)')
}

2

Reny TonyLâmpadaの回答、コメント#27は実際に問題を解決しましたが、Javaコードが提供され、Pythonが必要でした。要素の位置までスクロールしてクリックするPython関数を次に示します。

def scroll_to_and_click(xpath):
    element = TestUtil.driver.find_element_by_xpath(xpath)
    TestUtil.driver.execute_script('window.scrollTo(0, ' + str(element.location['y']) + ');')
    element.click()

これでChrome 34.0の問題が解決しました。Firefox 28.0とIE 11では害はありませんでした。これらのブラウザーは問題の影響を受けませんが、クリックする前に要素の位置までスクロールすることは問題ありません。


2

多分それは本当にきれいな解決策ではありませんが、うまくいきます:

try:
    el.click()
except WebDriverException as e:
    if 'Element is not clickable at point' in e.msg:
        self.browser.execute_script(
            '$("{sel}").click()'.format(sel=el_selector)
        )
    else:
        raise

2

ホバーをテストし、ツールチップの下のリンクをクリックする必要があったため、このバグが発生しました。解決策は、ツールチップを邪魔page.find('.sp-logo').hoverclick_linkならないように前に追加することでした。


2

面白いことに、私がさまざまな応答を見て過ごしている間、誰も明白なことを試したことはありませんでした。もちろん、私もそうではありませんでした。あなたのページが私のように複数回使用された同じID( "newButton"、)を持ち、必要なものが最初に見つかったものでない場合、おそらくこのエラーが発生します。最も簡単なこと(C#):

var testIt = driver.FindElements(By.Id("newButton"));

FindElementsではなくFindElementsであることに注意してください。

次に、検索から返された結果の数をテストします。2番目の場合は、次を使用できます。

testit[1].Click();

または、IDを再利用して修正する人を取得します。


これは、そのIDのボタンが複数あり、一度に1つしか表示されないためである場合、LINQを使用して表示されている最初の要素を検索し(.First(x => x.Visible)FindElements呼び出しに追加)、それがnullでない場合はそれをクリックします。
Sean Duggan

2

上記の提案をすべてテストした後、何も機能しませんでした。私はこのコードを作りました。動作しますが、美しくありません

public void click(WebElement element) {
    //https://code.google.com/p/selenium/issues/detail?id=2766 (fix)
    while(true){
        try{
            element.click();
            break;
        }catch (Throwable e){
            try {
                Thread.sleep(200);
            } catch (InterruptedException e1) {
                e1.printStackTrace();
            }
        }
    }
}

public void click(String css) {
    //https://code.google.com/p/selenium/issues/detail?id=2766 (fix)
    while(true){
        try{
            driver.findElement(By.cssSelector(css)).click();
            break;
        }catch (Throwable e){
            try {
                Thread.sleep(200);
            } catch (InterruptedException e1) {
                e1.printStackTrace();
            }
        }
    }
}

2

私は一種の力ずくのクリックをします、そしてそれは私のために働きます。

try:
    elem.click()
except:
    print "failed to click"
    size = elem.size
    mid_of_y = int(size["height"])/2
    stepts_to_do_to_left = int(size["width"])
    while stepts_to_do_to_left > 0:
        try:
            print stepts_to_do_to_left, mid_of_y
            action = webdriver.common.action_chains.ActionChains(driver)
            action.move_to_element_with_offset(elem, mid_of_y, stepts_to_do_to_left)
            action.click()
            action.perform()
            print "DONE CLICK"
            break
        except:
            pass

2

あなたがいる場合はjQueryページ上にロードされ、次のJavaScriptのコマンドを実行することができます。

"$('#" + element_id + "').click()"

Python executorの使用例:

driver.execute_script("$('#%s').click()" % element_id)

1

私は同じ問題を抱えていましたが、それはdivとdiv内のリンクとの間のIDの競合が原因でした。だからドライバーは私が望んでいたリンクの代わりにdivをクリックしていました。私はdiv idを変更し、それは適切に動作しました。

前:

<div id="logout"><a id="logout" href="logoutLink">logout</a></div>

後:

<div id="differentId"><a id="logout" href="logoutLink">logout</a></div>

あなたが問題を引き起こしたのは驚くことではありません。1つのページに1つのIDのみが存在する必要があります。それは、回避策ではなく、悪いデザインをほどいていた。
Dave Lawrence

1

DrupalでSeleniumを使用する場合:

    // Get element.
    $element = $this->driver->getElement('xpath=//input');        
    // Get screen location.
    $location = $element->getLocation();
    // To make sure that Chrome correctly handles clicking on the elements 
    // outside of the screen, we must move the cursor to the element's location.
    $this->driver->moveCursor($location['x'], $location['y']);

    // Optionally, set some sleep time (0.5 sec in the example below) if your
    // elements are visible after some animation.
    time_nanosleep(0, 500000000);

    // Click on the element.
    $element->click();
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.