Seleniumを使ってChromeであるサイトに自動ログインしてその処理を終えたら、コンソールを消してそのままChromeを使いたいのですが、やり方は分かりますでしょうか?Pyinstallerで--noconsoleというオプションがあるようですが、処理が終わるまでコンソールは出て欲しいです。
driver.quit() や driver.close() だとブラウザーも閉じてしまうので、やはり違います。
以下のコードだとドライバを削除するのですが、コンソールは消えないです。
Python
1os.system("taskkill /f /im C:\Python\Driver\chromedriver.exe")
気になる質問をクリップする
クリップした質問は、後からいつでもMYページで確認できます。
またクリップした質問に回答があった際、通知やメールを受け取ることができます。
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
回答1件
0
ベストアンサー
taskkill
コマンドや chromedriver.exe
といったファイル名から、対象の環境は Windows かと御見受け致しますが、この場合 「Python 側のコンソールはスクリプトが終わるまで開き、然し chromedriver や Chrome のコンソールは消したい」 という要件の実現は少々面倒です。具体的には、以下 2 つの対応を行う必要があるかと存じます。
- chromedriver の
detach
オプションを有効にし、 chromedriver プロセスだけを終了させる - 子プロセス生成のどこかの時点で、 親プロセスからのコンソールの継承を断ち切る
1) chromedriver の detach オプションを有効にする
まず、 Selenium (WebDriver) の処理を終了させた後に Chrome を使いたいということですから、 Chrome は生存させたまま chromedriver プロセスに終了してもらう 必要が御座いますが、こちらは単純に、 その目的のための detach というオプションが chormedriver に用意されている ので、これを有効にする ことで実現ができます。
但し、 WebDriver.quit()
メソッド を呼ぶと、結局 Chrome のセッションごとすべてを終了させてしまうので、 代わりに Service.stop()
メソッドを呼び出し、 chromedriver のみを終了させる ことが肝要です。
python
1from selenium import webdriver 2from selenium.webdriver.chrome.options import Options 3 4options = Options() 5options.add_experimental_option('detach', True) 6 7driver = webdriver.Chrome(options=options) 8 9driver.get('https://teratail.com/') 10 11# do something... 12 13driver.service.stop()
2) 親プロセスからのコンソールの継承を断ち切る
さて、以上の対応で Chrome を生存させたまま、 chromedriver や Python のプロセスだけを終了させることが可能となります。実際、タスクマネージャー等を閲覧すると、 Chrome 以外の関係するプロセスは既に終了していることが確認出来るかと存じます。ところが、これでも 問題としている「コンソール画面」は残ってしまっている はずです (仰っている taskkill
コマンドの利用時と同じ結果ですね) 。
これはなぜかというと、 Python が使用していたコンソールを、 chromedriver を経由して継承した Chrome のプロセスがそのまま使用している ことが原因です。
Windows 環境でのコンソールプロセスは、例えば コンソールプロセスのコンソール生成に関する Microsft Docs の記事 に "By default, a console process inherits its parent's console" と記載されている通り、デフォルトでは 子プロセスとして起動されたとき、親プロセスがコンソールを持っていればそのコンソールを継承して動作 します。結果、 Chrome プロセスがコンソールを使い続けている限り、親の Python が使っていたコンソールが解放されず、画面もまた閉じられないという状況が生じ得ます。
この問題に対処するには幾つかの方法が考えられますが、比較的簡単な方法としては次の何れかの方法が良いのではないでしょうか。
2-a) プロセス生成時に CREATE_NO_WINDOW
フラグを渡す
まず一つ目としては、 chromedriver プロセスを WebDriver が起動する際、 CREATE_NO_WINDOW
フラグを渡す 方法が考えられます。
このプロセス生成時のフラグについては Microsoft Docs の該当ページ を御参照頂くと良いのですが、大雑把に言ってしまうと、 「コンソールアプリケーションをコンソール画面を表示させずに動作させる」 フラグであり、結果的に親とは別の非表示のコンソールを使用する形で実行されるため、Python と同じコンソール画面を使用し続けるような状況を回避することが可能になります。
※ CREATE_NEW_CONSOLE
や DETACHED_PROCESS
も似た説明で紛らわしいのですが、何れも「(必要であれば) 親プロセスとは別のコンソール画面を開く」だけであり、結局 Chrome の使用するコンソール画面が表示されたまま残り続ける問題は解決しません
但し Windows 環境の場合、このフラグは subprocess.Popen()
の引数として 渡すことが可能なのですが、 Selenium が子プロセスを生成する Service.start()
の実装はこのように なっており、そのままではフラグを渡すことができません。
ですから、該当の selenium/webdriver/common/service.py
を編集するか、あるいは次のようにモンキーパッチを一時的に当て、 creationflags を無理矢理渡す必要が出て参ります。
python
1from subprocess import Popen, CREATE_NO_WINDOW 2 3_original_constructor = Popen.__init__ 4 5def _patched_constructor(*args,**kwargs): 6 kwargs['creationflags'] = CREATE_NO_WINDOW 7 8 return _original_constructor(*args, **kwargs) 9 10Popen.__init__ = _patched_constructor 11 12driver = webdriver.Chrome(options=options) 13 14Popen.__init__ = _original_constructor
2-b) Chrome に enable-logging
起動オプションを与えず、コンソールを使わせない
もう一つの考え方として、 そもそも Chrome をコンソールプロセスとして動作させない 、という考え方も御座います。
普段、単にブラウザとして Chrome を起動した場合、特にコンソールは使用せずコンソール画面も開きませんが、これが chromedriver 経由で起動した場合にコンソールを使用するようになるのは、 chromedriver が Chrome にデフォルトで enable-logging
という起動オプションを与え、ログ出力を有効にしている ことが原因です。
幸い、このデフォルトの起動オプションは chromedriver の excludeSwitches
オプションで無効化出来ますので、例えば以下のようにするだけでも、 Chrome がコンソールを使用しなくなりコンソール画面が開いたままという状況はやはり回避できるかと存じます。
python
1options.add_experimental_option('excludeSwitches', ['enable-logging']) 2 3driver = webdriver.Chrome(options=options)
但し、これにより Chrome のログ出力機能 全体が無効になってしまいますので、その点は御留意頂く必要が御座います。
2-c) conhost.exe
の画面を探して非表示にする
※ GetConsoleWindow()
の存在を知らず、誤った回答となっておりましたので、修正致しました
その他の方法としては、 コンソール画面は conhost.exe
という別プロセスによって実現されている のですが、 Python スクリプトが 自身の使用している conhost.exe
の画面を探し出し、 ShowWindow()
API によって非表示にしてから終了する というやり方も考えられます。
python
1import ctypes 2import subprocess 3 4console_hwnd = ctypes.windll.kernel32.GetConsoleWindow() 5ctypes.windll.user32.ShowWindow(console_hwnd, subprocess.SW_HIDE)
この方法であれば、 スクリプト自身が必要な場合のみに不要となったコンソール画面を非表示とできる メリットが御座いますが、不用意に実行すると、例えば開発作業中に使用していた cmd.exe
の画面を意図せずに消してしまい、操作ができなくなるような事故も生じ得ますので、御利用には御注意下さいませ。
投稿2020/04/18 08:47
編集2020/04/18 09:55総合スコア1017
あなたの回答
tips
太字
斜体
打ち消し線
見出し
引用テキストの挿入
コードの挿入
リンクの挿入
リストの挿入
番号リストの挿入
表の挿入
水平線の挿入
プレビュー
質問の解決につながる回答をしましょう。 サンプルコードなど、より具体的な説明があると質問者の理解の助けになります。 また、読む側のことを考えた、分かりやすい文章を心がけましょう。
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
2020/04/20 01:14