web-dev-qa-db-ja.com

セレンを使用してwebdriverで開いたブラウザーに再接続するにはどうすればよいですか?

いくつかの未知の理由により、私のブラウザは私のリモートサーバーのテストページを非常にゆっくりと開きます。スクリプトを終了した後にブラウザに再接続できるかどうかを考えていますが、webdriver.quit()を実行しないと、ブラウザが開いたままになります。おそらく、フックまたはWebdriverハンドルの一種です。 Selenium APIドキュメントを調べましたが、機能が見つかりませんでした。私はChrome 62、x64、windows 7、Selenium 3.8.0を使用しています。質問が解決できるかどうかは非常にありがたいです。

11
imbaiye

No、スクリプトを終了した後、以前の_Web Browser_セッションに再接続できません。 _Session ID_Cookies、および以前の_Browsing Session_から他のセッション属性を抽出できたとしてもそれでも、これらの属性をフックとしてWebDriverに渡すことはできません。

よりクリーンな方法はwebdriver.quit()を呼び出してから、新しい_Browsing Session_をスパンすることです。

歴史:

以前は、いくつかの議論があり、既存の実行中のブラウジングセッションにWebDriverを再接続する試みがありました。これらのQAでディスカッションを見つけることができます。

8
DebanjanB

はい、それは実際には非常に簡単です。

Selenium <-> webdriverセッションは接続URLとsession_idで表され、既存のセッションに再接続するだけです。

免責事項-このアプローチはSeleniumの内部プロパティ(ある意味では「プライベート」)を使用しており、新しいリリースでは変更される可能性があります。運用コードには使用しない方がよいでしょう。最後に説明されている警告/リソースの排出のため、リモートSE(ハブ、またはBrowserStack/Sauce Labsのようなプロバイダー)に対しては使用しない方が良いでしょう。

Webdriverインスタンスが開始されると、前述のプロパティを取得する必要があります。サンプル:

_from Selenium import webdriver

driver = webdriver.Chrome()
driver.get('https://www.google.com/')

# now Google is opened, the browser is fully functional; print the two properties
# command_executor._url (it's "private", not for a direct usage), and session_id

print(f'driver.command_executor._url: {driver.command_executor._url}')
print(f'driver.session_id: {driver.session_id}')
_

これら2つのプロパティがわかったので、別のインスタンスが接続できます。 「トリック」は、Remoteドライバーを開始し、上記の__url_を提供することです。したがって、実行中のSeleniumプロセスに接続します。

_driver2 = webdriver.Remote(command_executor=the_known_url)  
# when the started Selenium is a local one, the url is in the form 'http://127.0.0.1:62526'
_

これが実行されると、新しいブラウザウィンドウが開いているのがわかります。
これは、ドライバを開始すると、Seleniumライブラリが自動的に新しいセッションを開始するためです。これで、2つのセッション(ブラウザインスタンス)を持つ1つのWebdriverプロセスができました。

URLに移動すると、その新しいブラウザーインスタンスで実行されていることがわかります。前回の起動で残ったインスタンスではなく、望ましい動作ではありません。
この時点で、2つのことを行う必要があります。a)現在のSEセッション(「新しいセッション」)を閉じ、b)このインスタンスを前のセッションに切り替えます。

_if driver2.session_id != the_known_session_id:   # this is pretty much guaranteed to be the case
    driver2.close()   # this closes the session's window - it is currently the only one, thus the session itself will be auto-killed, yet:
    driver2.quit()    # for remote connections (like ours), this deletes the session, but does not stop the SE server

# take the session that's already running
driver2.session_id = the_known_session_id

# do something with the now hijacked session:
driver.get('https://www.bing.com/')
_

そして、それだけです-これで、すべてのプロパティ(Cookie、LocalStorageなど)を使用して、前の/すでに存在するセッションに接続されました。

ちなみに、新しいリモートドライバーを開始するときに_desired_capabilities_を指定する必要はありません。これらは保存され、引き継いだ既存のセッションから継承されます。


警告-SEプロセスが実行されていると、システム内のリソースが一部消費される可能性があります。

コードの最初の部分のように、起動して閉じない場合は常に、手動で強制終了するまでそのままです。つまり、たとえばWindowsでは、「chromedriver.exe」プロセスが表示されます。このプロセスが終了したら、手動で終了する必要があります。リモートのSeleniumプロセスに関して接続しているドライバーによって閉じることはできません。
理由-ローカルブラウザインスタンスを開始し、そのquit()メソッドを呼び出すと、2つの部分があります。最初の部分は、Seleniumインスタンスからセッションを削除することです( 2番目のコード部分で行われます)、もう1つはローカルサービス(chrome/geckodriver)を停止することです。通常は問題なく動作します。

問題は、リモートセッションの場合、2番目の要素が欠落していることです。ローカルマシンはリモートプロセスを制御できません。これが、そのリモートのハブの働きです。つまり、2番目の部分は文字どおりpass pythonステートメント-何もしないことです。

リモートハブで開始するSeleniumサービスが多すぎて、それを制御できない場合は、そのサーバーからのリソースの消耗につながります。 BrowserStackのようなクラウドプロバイダーはこれに対して対策を講じます-彼らは過去60秒間など活動のないサービスを閉鎖しています-これはあなたがしたくないことです。

ローカルSEサービスについては、忘れていた孤立したSeleniumドライバからOSを時々クリーンアップすることを忘れないでください:)

5
Todor Minakov

なぜブラウザウィンドウを開いたままにしておくと遅くなるという問題を解決できると思いますか?セッションを閉じずに、つまり、あなたが言ったようにdriver.quit()を呼び出さずにテストを実行し続けるだけです。ここでの質問は、独自のランナーに付属するフレームワークですか?きゅうりが好き?

いずれの場合も、「セットアップ」および「クリーンアップ」コードが必要です。したがって、「クリーンアップ」フェーズ中にブラウザが初期状態に戻っていることを確認する必要があります。つまり:

  • 空白のページが表示される
  • セッションのCookieは消去されます
0
Eugene S