「出来たぜやったね」を強調する手もないではないけれどだがしかし。
selenium webdriver で chrome をコントロールする動機のほとんど大半が web サービスから何らか結果を得るための操作の自動化、すなわちアウトプットが得られればいいというものなので、その向きには「開いている chrome のインスタンスにアタッチして、それをコントロールする」ことは大抵考えなくていい。つまりは、プロセスとして chrome をバックグラウンドで起動してそのインスタンスをコントロール出来れば良い。ワタシが書いたネタであれば例えばこれとか。
けれども、例えばメモリが何らかの理由で逼迫しているとして、そうしたケースで「メモリ喰いの「タブを大量に開いた」chrome を整理する術が欲しい」と思ったとする。というか思った。
今ワタシはこのページを書くための chrome を、80くらいのタブを開いた状態で書いている。色んな調べものをしつつ、エロいタブも日常的に開いている、とかだと、気付いたらこんな状態になってることが多い。ここまでタブを開いていると、結構同じページを複数開いていたりするし、もうとっくに用済みになってるページも開きっぱなしになってることも多い。そしてメモリが逼迫してる状態だと「各々のタブにマウス操作などで移動してみて、開きっぱなしにしとく意味がないと判断出来るなら閉じる」という繰り返し行為そのものが「重くて操作に耐えない」ので、ということ。このために、たとえばコンソールからタブを閉じる操作は出来ないだろうか、みたいなことを考えたわけだ。
けれどもこれが非常によろしくない。
最も望むものに近かったのが見出しにした「chrome.exe --remote-debugging-port
」を使う方法なのだが、まぁ…「今開いている全タブ」にアクセス出来んのだわ。これについての情報はどこにもない。あと、キー操作なども出来ないなど制約が非常に多くて、救世主度は非常に低い。
これをするためにはまずは:
参考にしたサイトが皆 9222 を選んでるんで、指定しなければ自動でポートが開いてたりしないんだろうかと思ったけれど、そうでもなさそう。いや、あるかもしれんけど、情報は一切見つからず。ともあれ、この状態で常に chrome を起動するようにしておけば:
1 # -*- coding: utf-8 -*-
2 from selenium import webdriver
3 from selenium.webdriver.chrome.options import Options
4
5 chrome_options = Options()
6 chrome_options.add_experimental_option("debuggerAddress", "127.0.0.1:9222")
7 driver = webdriver.Chrome(options=chrome_options)
8 for h in driver.window_handles:
9 driver.switch_to.window(h)
10 print(h, driver.title)
ワタシのその「80くらい開いてる」タブのほとんどが無視され、このスクリプトは20くらいだけのタブ切り替えを「してくれる」。この「20くらいしか」という制約が気にならない用途であるならば、例えば「それらタブを全部閉じる」ということは出来る。
どの「20くらい」になるかは、アクティブな chrome インスタンスで最後に手動操作した状態に依存する。LRU みたいなことだろう、きっと。最後にアクティブにしたもののキャッシュにアクセス出来ている、という感じかもしれない。
あと、この debuggerAddress は REST API を提供してくれている。9222 で設定して起動したなら http://127.0.0.1:9222/json にアクセスしてみよ。これに基づいてなんらか処理をすることも無論可能で:
1 # -*- coding: utf-8 -*-
2 import requests # これも標準バンドルではないので pip install しとくれ
3 from selenium import webdriver
4 from selenium.webdriver.chrome.options import Options
5
6 chrome_options = Options()
7 chrome_options.add_experimental_option("debuggerAddress", "127.0.0.1:9222")
8 driver = webdriver.Chrome(options=chrome_options)
9 res = requests.get("http://127.0.0.1:9222/json")
10 #for h in driver.window_handles:
11 # driver.switch_to.window(h)
12 # print(h, driver.title)
13 for d in [d for d in res.json() if d["type"] == "page"]:
14 print(d["type"])
15 driver.switch_to.window(d["id"])
16 print(driver.title)
はっきりいって本質的にやってることは何ら変わらないので、「20しか…」問題の解決にはならないけれど、まぁ知識として知っといて損はないかなというレベル。
てなわけで、メモとして書いておく価値はないとは言えないけれど、即戦力として使えるものではなかった、てことで。