在使用硒的Ruby中,难以单击Google搜索

时间:2018-12-29 15:19:36

标签: ruby selenium selenium-webdriver

到此为止,我打开了Firefox浏览器,导航到google,并找到了google搜索元素

irb(main):001:0> require 'selenium-webdriver'
=> true

irb(main):002:0> driver = Selenium::WebDriver.for:firefox
=> #<Selenium::WebDriver::Firefox::Marionette::Driver:0x..fb3c81796cc82b708 browser=:firefox>

irb(main):003:0> driver.navigate().to("http://www.google.com")
=> nil

irb(main):188:0> driver.find_element(:name, "q").send_keys "fff"
=> nil    

irb(main):112:0> driver.find_element(:name, "btnK");
=> #<Selenium::WebDriver::Element:0x5fb450f4379c50ce id="d767311c-27a2-3544-8f11-e4edc9736588">

irb(main):113:0> driver.find_element(:name, "btnK").attribute('value');
=> "Google Search"

但是我无法点击它!

irb(main):114:0> driver.find_element(:name, "btnK").click
Traceback (most recent call last):
       16: from /usr/local/lib/ruby/gems/2.5.0/gems/selenium-webdriver-3.141.0/lib/selenium/webdriver/remote/w3c/bridge.rb:552:in `execute'
       15: from /usr/local/lib/ruby/gems/2.5.0/gems/selenium-webdriver-3.141.0/lib/selenium/webdriver/remote/bridge.rb:166:in `execute'
       14: from /usr/local/lib/ruby/gems/2.5.0/gems/selenium-webdriver-3.141.0/lib/selenium/webdriver/remote/http/common.rb:62:in `call'
       13: from /usr/local/lib/ruby/gems/2.5.0/gems/selenium-webdriver-3.141.0/lib/selenium/webdriver/remote/http/default.rb:104:in `request'
       12: from /usr/local/lib/ruby/gems/2.5.0/gems/selenium-webdriver-3.141.0/lib/selenium/webdriver/remote/http/common.rb:84:in `create_response'
       11: from /usr/local/lib/ruby/gems/2.5.0/gems/selenium-webdriver-3.141.0/lib/selenium/webdriver/remote/http/common.rb:84:in `new'
       10: from /usr/local/lib/ruby/gems/2.5.0/gems/selenium-webdriver-3.141.0/lib/selenium/webdriver/remote/response.rb:32:in `initialize'
        9: from /usr/local/lib/ruby/gems/2.5.0/gems/selenium-webdriver-3.141.0/lib/selenium/webdriver/remote/response.rb:69:in `assert_ok'
        8: from clickElement@chrome://marionette/content/listener.js:1209:5
        7: from navigate@chrome://marionette/content/listener.js:409:13
        6: from navigate/<@chrome://marionette/content/listener.js:410:13
        5: from clickElement/<@chrome://marionette/content/listener.js:1210:14
        4: from interaction.clickElement@chrome://marionette/content/interaction.js:130:11
        3: from webdriverClickElement@chrome://marionette/content/interaction.js:159:11
        2: from ElementNotInteractableError@chrome://marionette/content/error.js:286:5
        1: from WebDriverError@chrome://marionette/content/error.js:178:5
Selenium::WebDriver::Error::ElementNotInteractableError (Element <input name="btnK" type="submit"> could not be scrolled into view)
irb(main):115:0> 

它说元素“无法滚动到视图中”!

我可以做driver.find_element(:tag_name, "body").send_keys :page_down;来往下翻页。提到哪一点参见send_keys https://www.rubydoc.info/gems/selenium-webdriver/Selenium%2FWebDriver%2FElement%3Asend_keys的ruby硒文档。我看到了键代码列表https://www.rubydoc.info/gems/selenium-webdriver/Selenium/WebDriver/Keys#KEYS-constant。并且还列出了https://github.com/SeleniumHQ/selenium/blob/master/rb/lib/selenium/webdriver/common/keys.rb。或者我可以手动向下翻页。但是滚动(至少在通常意义上来说)似乎不是问题,我仍然遇到该错误。也许是在我可以切换到的框架中,我不知道是哪个。

按钮当然是可见的。这只是常规的Google搜索页。

我可以找到该按钮,但是我看不到如何单击它,因为.click对我不起作用。

已添加

回复评论,询问我Google推荐框是否使按钮模糊。我可以在浏览器中看到按钮没有被混淆,因为有时我已经手动完成了转义操作,或者单击了背景窗口(以消除这种情况。我使用的是IRB,因此手动运行每条语句,所以我有时间这样做)。但是我也使用代码进行了转义,并且转义功能可以摆脱建议框,但是在尝试单击按钮时仍然存在相同的错误

3 个答案:

答案 0 :(得分:2)

这就是我告诉您使用WATIR的方式,如果您使用过WATIR,则不会出现此问题。您的代码中的问题,它不是在等待可见性。最近,Chrome驱动程序还添加了隐式等待点击,因此,如果您设置了隐式等待,它将等待可见性。否则,请移至WATIR,这是一个很好的包装程序,不需要通过驱动程序等待。在WATIR中,等待元素状态的操作是通过本地语言绑定发生的,因此请使用此硒代码

require 'selenium-webdriver'
driver = Selenium::WebDriver.for :chrome
driver.manage.timeouts.implicit_wait = 10
driver.navigate().to("http://www.google.com")
driver.find_element(:name, "q").send_keys "fff"
driver.find_element(:name, "btnK").click

请记住,此硒代码不适用于Firefox,因为尚未为Firefox添加隐式等待点击。

由于WATIR正在处理本地语言绑定的时间安排,因此无论您使用的是Chrome还是Firefox都没关系,

WATIR代码(默认为Chrome)

require 'watir'
b=Watir::Browser.new
b.goto 'www.google.com'
b.text_field(name: 'q').set 'fff'
b.button(name: 'btnK').click

如果要驱动Firefox

b=Watir::Browser.new :firefox

答案 1 :(得分:1)

在评论中讨论此问题时,我编写了一些C#代码来演示如何等待C#中的可点击操作

new WebDriverWait(Driver, TimeSpan.FromSeconds(5)).Until(ExpectedConditions.ElementToBeClickable(By.Name("btnK"))).Click();

在编写我发布的C#代码的过程中,我认为我明白了问题所在。当您开始在搜索框中输入内容时,会出现一个包含建议搜索的下拉列表。这涵盖了您尝试单击的“ Google搜索”按钮。但是,下拉菜单本身的底部显示了另一个“ Google搜索”按钮。您应该打印一个(:name, "btnK")元素的计数...我假设它将打印2(如果添加了适当的等待)。从那里,您只需要单击顶部的那个。

另一种选择是在搜索字符串的末尾发送\ r \ n,避免整个问题……或者您可以导航到最终的搜索URL并节省更多的麻烦和时间。

从barlop添加了笔记

为澄清起见,这与显示的建议弹出窗口无关(并且必须摆脱弹出窗口)..与等待无关(自从我与IRB合作以来,我自然就在等待)。而且我已经单击了外部或单击逃逸来摆脱弹出窗口。问题是,Jeff的回答使我意识到了这一点-即使弹出窗口消失了,仍然有两个带有btnK名称的按钮。因此,使用find_elements而不是find_element,然后在第二个运行.click可以! (此外,将find_elements(复数)用作name属性是有意义的,因为如此处答案中所述:https://stackoverflow.com/questions/5518458/does-a-name-attribute-have-to-be -unique-in-a-html-document。name属性不是唯一的/不是唯一的标识符。

答案 2 :(得分:0)

但是您可以使用javascript(将javascript发送到浏览器)进行点击。

b=driver.find_element(:name, "btnK")

driver.execute_script("arguments[0].click();",b)

Jeff解释了为什么javascript方法(带有selenium的selenium)可以在任一按钮上工作,而非javascript方法(没有javascript的硒)只能在一个按钮上工作,他写道:“两个按钮都可以,JS单击将单击任何元素,无论它在何处...或它是否可见,等等。Selenium旨在像用户一样与页面进行交互,因此由于错误而无法单击该元素。“