Pythonで以下を使用してphantomjs
を開始して閉じます。
from Selenium import webdriver
driver = webdriver.PhantomJS()
driver.get(url)
html_doc = driver.page_source
driver.close()
それでも、スクリプトの実行が終了した後、Mac Activity Monitorでphantomjs
のインスタンスを見つけます。実際、スクリプトを実行するたびに、新しいプロセスphantomjs
が作成されます。
ドライバーを閉じる方法は?
.close()
メソッドは、ドライバーインスタンスに関連付けられたすべてのリソースを解放することを保証しません。これらのリソースには、ドライバーの実行可能ファイル(この場合はPhantomJS)が含まれますが、これに限定されないことに注意してください。 .quit()
メソッドは、実行可能プロセスの終了を含む、ドライバーのすべてのリソースを解放するように設計されています。
2016年7月の時点では、driver.close()
とdriver.quit()
では不十分でした。それはnode
プロセスを強制終了しましたが、それが生成したphantomjs
子プロセスは強制終了しませんでした。
このGitHubの問題 に関する議論に続いて、私のために働いた唯一のソリューションは次のように実行することでした:
import signal
driver.service.process.send_signal(signal.SIGTERM) # kill the specific phantomjs child proc
driver.quit() # quit the node proc
マシン上でPhantomJSを起動する複数のスレッド/プロセスがある場合、これは明らかに問題を引き起こすことに注意してください。
同じ問題に苦しんでいる人々を見たことがありますが、私にとって最も簡単な回避策/ハックは、コマンドラインからPythonを呼び出した後、driver.close()
またはdriver.quit()
:
pgrep phantomjs | xargs kill
Windowsマシンでも同様の問題が発生していました。私も運がなかった
driver.close()
または
driver.quit()
実際にPhantomJSウィンドウを閉じますが、両方を使用すると、PhantomJSウィンドウが最終的に閉じて適切に終了しました。
driver.close()
driver.quit()
driver.quit()
はWindows 10では機能しませんでしたので、driver.close()
を呼び出した直後に次の行を追加しました。
os.system('taskkill /f /im phantomjs.exe')
どこで
/f = force
/im = by image name
また、これはWindows専用のソリューションであるため、os.name == 'nt'
使用しているOSは何ですか? POSIX OSを使用している場合、次のケースに対応すると思います。
プルリクエストを作成しましたが、拒否されました。 https://github.com/SeleniumHQ/Selenium/pull/2244
しかし、私は明らかにそれが正しいと思います。したがって、私は問題を発行しました。 https://github.com/SeleniumHQ/Selenium/issues/2272
この問題の根本的な原因は、ゴーストドライバーモードphatmojsの終了方法が正しくないことです。最後にゴーストドライバーモードphantomjsのシャットダウンAPIを使用しません。
LinuxまたはOSXのnpmにインストールしたphantomjsの場合、SeleniumはphantomjsのPopenを呼び出し、phantomjsはlib/phantomjs.jsのspawnを呼び出します。現時点では、Seleniumは親、phantomjsは子、lib/phantomjs.jsは孫です。
親(Selenium)でquit()を呼び出し、SIGTERMを子(phantomjs)に送信します。そして、child(phantomjs)は、子のSIGTERMハンドラー関数でSIGTERMをgrandchild(lib/phantomjs.js)に送信します。
子がSIGTERMを孫に送信する前に親がSIGKILLを子に送信すると、孫はゾンビになります。
このプルリクエストttps://github.com/SeleniumHQ/Selenium/pull/2244は、ゴーストドライバーモードシャットダウンAPIを使用してシャットダウンされます。
def send_remote_shutdown_command(self):
super(Service, self).send_remote_shutdown_command() ## ADD A NEW LINE HERE
if self._cookie_temp_file:
os.close(self._cookie_temp_file_handle)
os.remove(self._cookie_temp_file)
他の解決策は、「self.process.ternimate()」と「self.process.kill()」の間でスリープします。 ttps://github.com/SeleniumHQ/Selenium/blob/051c8b110a1aec35247cd45fa4db85c6e522cdcb/py/Selenium/webdriver/common/service.py#L151-L153
self.process.terminate()
time.sleep(1) ## ADD A NEW LINE HERE
self.process.kill()
self.process.wait()
また、pythonスクリプトをSeleniumを使用してMacで実行し、PhantomJSをWebドライバーとして使用して何らかの処理を行います。
テストを実行しているとき、注意すべき3つのプロセスがあります。
_$ ps -ef | grep [p]hantomjs
501 28085 24925 0 9:03pm ttys002 0:00.34 python test.py
501 28088 28085 0 9:03pm ttys002 0:00.14 node /usr/local/bin/phantomjs --cookies-file=/var/folders/nq/hjz03w6d4fs620197d_zwg0m0000gn/T/tmp8xLNaH --webdriver=55075
501 28090 28088 0 9:03pm ttys002 0:00.71 /usr/local/lib/node_modules/phantomjs/lib/phantom/bin/phantomjs --cookies-file=/var/folders/nq/hjz03w6d4fs620197d_zwg0m0000gn/T/tmp8xLNaH --webdriver=55075
_
2番目の列はプロセス番号であり、3番目の列はプロセスの親です。私のテストスクリプトは親です。テストスクリプトを親として持つノードプロセスがあり、そのノードプロセスを親とする別のPhantomJSプロセスがあります。なぜ2つのPhantomJSプロセスがあるのかを聞かないでください。
とにかく、私のMacのアクティビティモニターでは、これを見ることができます:
PID番号28090に注意してください。
私のテストがこれを実行し終えると、あなたと同じようにプロセスが動き回ります。まだ実行中のプロセスを確認すると、次のことがわかります。
_$ ps -ef | grep [p]hantomjs
501 28090 1 0 9:03pm ttys002 0:18.93 /usr/local/lib/node_modules/phantomjs/lib/phantom/bin/phantomjs --cookies-file=/var/folders/nq/hjz03w6d4fs620197d_zwg0m0000gn/T/tmp8xLNaH --webdriver=55075
_
したがって、driver.quit()
はPID番号28088のノードプロセスを終了するように見えますが、その子は孤立したままになります。これが意図的なものかどうかはわかりません。意図的でない場合は、コードでこのプロセスを終了する「適切な」方法はないと思います。
したがって、driver.quit()
の直後に、あなたの言語の_kill -9 28090
_と同等のものを使用します