Rubyと筋肉とギターとわたし

筋トレが仕事です

【Selenium】location_once_scrolled_into_viewでelement not interactableが発生したときの対処方法

どうもてぃ。

自社開発でseleniumをよく使うのですが、とあるサイトをクローリングしているときに出くわしたエラーを力技で解決したので備忘録として残します。

環境

コード

require 'selenium-webdriver'

options = Selenium::WebDriver::Chrome::Options.new
client = Selenium::WebDriver::Remote::Http::Default.new
wait = Selenium::WebDriver::Wait.new(timeout: 20)
options.add_argument('--headless')
options.add_argument('--disable-gpu')
options.add_argument('--no-sandbox')
options.add_argument('--disable-dev-shm-usage')
options.add_argument('--window-size=1920,1080')
options.add_argument('--lang=ja-JP')
driver = Selenium::WebDriver.for(:chrome, capabilities: [options], http_client: client)

driver.get('https://example.com')
footer = driver.find_element(:tag_name, 'footer')
footer.location_once_scrolled_into_view

エラー内容

element not interactable
  (Session info: chrome=109.0.5414.74)
#0 0x555fe9d48303 <unknown>: element not interactable (Selenium::WebDriver::Error::ElementNotInteractableError)
  (Session info: chrome=109.0.5414.74)
        from #1 0x555fe9b1cbbd <unknown>
        from #2 0x555fe9b530bc <unknown>
        from #3 0x555fe9b52669 <unknown>
        from #4 0x555fe9b79982 <unknown>
        from #5 0x555fe9b4e22f <unknown>
        from #6 0x555fe9b79b4e <unknown>
        from #7 0x555fe9b9188c <unknown>
        from #8 0x555fe9b79753 <unknown>
        from #9 0x555fe9b4ca14 <unknown>
        from #10 0x555fe9b4db7e <unknown>
        from #11 0x555fe9d9732e <unknown>
        from #12 0x555fe9d9ac0e <unknown>
        from #13 0x555fe9d7d610 <unknown>
        from #14 0x555fe9d9bc23 <unknown>
        from #15 0x555fe9d6f545 <unknown>
        from #16 0x555fe9dbc6a8 <unknown>
        from #17 0x555fe9dbc836 <unknown>
        from #18 0x555fe9dd7d13 <unknown>
        from #19 0x7f3bf207e609 start_thread
        from /home/motty/.asdf/installs/ruby/3.1.2/lib/ruby/gems/3.1.0/gems/selenium-webdriver-4.7.1/lib/selenium/webdriver/remote/response.rb:56:in `assert_ok'
        from /home/motty/.asdf/installs/ruby/3.1.2/lib/ruby/gems/3.1.0/gems/selenium-webdriver-4.7.1/lib/selenium/webdriver/remote/response.rb:35:in `initialize'
        from /home/motty/.asdf/installs/ruby/3.1.2/lib/ruby/gems/3.1.0/gems/selenium-webdriver-4.7.1/lib/selenium/webdriver/remote/http/common.rb:83:in `new'
        from /home/motty/.asdf/installs/ruby/3.1.2/lib/ruby/gems/3.1.0/gems/selenium-webdriver-4.7.1/lib/selenium/webdriver/remote/http/common.rb:83:in `create_response'
        from /home/motty/.asdf/installs/ruby/3.1.2/lib/ruby/gems/3.1.0/gems/selenium-webdriver-4.7.1/lib/selenium/webdriver/remote/http/default.rb:103:in `request'
        from /home/motty/.asdf/installs/ruby/3.1.2/lib/ruby/gems/3.1.0/gems/selenium-webdriver-4.7.1/lib/selenium/webdriver/remote/http/common.rb:59:in `call'
        from /home/motty/.asdf/installs/ruby/3.1.2/lib/ruby/gems/3.1.0/gems/selenium-webdriver-4.7.1/lib/selenium/webdriver/remote/bridge.rb:625:in `execute'
        from /home/motty/.asdf/installs/ruby/3.1.2/lib/ruby/gems/3.1.0/gems/selenium-webdriver-4.7.1/lib/selenium/webdriver/remote/bridge.rb:411:in `send_keys_to_element'
        from /home/motty/.asdf/installs/ruby/3.1.2/lib/ruby/gems/3.1.0/gems/selenium-webdriver-4.7.1/lib/selenium/webdriver/remote/bridge.rb:493:in `element_location_once_scrolled_into_view'
        from /home/motty/.asdf/installs/ruby/3.1.2/lib/ruby/gems/3.1.0/gems/selenium-webdriver-4.7.1/lib/selenium/webdriver/common/element.rb:307:in `location_once_scrolled_into_view'
        from scraping.rb:49:in `block (2 levels) in <main>'
        from scraping.rb:36:in `each'
        from scraping.rb:36:in `block in <main>'
        from scraping.rb:24:in `each'
        from scraping.rb:24:in `<main>'

よくわからん…

動的な要素だからとか??

力技を実行

jsの力を発動します。

seleniumでjsを実行する場合はexecute_scriptを使用します。

require 'selenium-webdriver'

options = Selenium::WebDriver::Chrome::Options.new
client = Selenium::WebDriver::Remote::Http::Default.new
wait = Selenium::WebDriver::Wait.new(timeout: 20)
options.add_argument('--headless')
options.add_argument('--disable-gpu')
options.add_argument('--no-sandbox')
options.add_argument('--disable-dev-shm-usage')
options.add_argument('--window-size=1920,1080')
options.add_argument('--lang=ja-JP')
driver = Selenium::WebDriver.for(:chrome, capabilities: [options], http_client: client)

driver.get('https://example.com')
footer = driver.find_element(:tag_name, 'footer')
driver.execute_script("window.scrollTo(#{footer.location.x}, #{footer.location.y});")

要素の座標はdriver.find_elementして取得した要素に対して、locationにアクセスしてあげればx座標とy座標が入ってるので、この子たちを使ってあげましょう。

終わり

実際のコードは画像をfind_elementしていて、headless modeで起動せずに目視でちゃんと要素が表示されているにも関わらず、タイトルのようなエラーが出ていました。

解決策を探しているうちにissueも上がっていた気がしますが、なんかcloseされてたので今回は力技でひとまず解決。

同じエラーが発生したときの正攻法(?)として誰かの力になればばばば。

おつでした。