AppleScript を使って Safari から情報を得る の Firefox 版です。 ほとんど AI にきいただけだが、備忘録として書き残します。 使用している環境は Ubuntu 26.04 LTS Desktop です。
余談ですが、Ubuntu 26.04 Desktop は気に入っている。標準のターミナルがよい。 Ubuntu 24.04 Desktop はときどき使っていてあまり気に入っていなかったので、 今度は Cosmic を試すか、くらいに思っていたが、26.04 が気に入ったのでこれを使って行こうと今のところ考えている。
Firefox には Marionette という機能が備わっているらしい。 これを有効にして firefox を起動する。
firefox --marionette
常時 marionette オプションを有効にする方法は後述
これで 127.0.0.1:2828 で firefox が コマンドを待ち受けるようになるので、これを使えばOKらしい。
python3 のコードをAIが教えてくれた:
#!/usr/bin/env python3
# page -> text of the current tab
# page url -> URL of the current tab
# page title -> title of the current tab
import json, socket, sys
class Marionette:
def __init__(self, host="127.0.0.1", port=2828):
self.sock = socket.create_connection((host, port))
self.msg_id = 0
self._recv() # server greeting
def _recv(self):
length = b""
while not length.endswith(b":"):
c = self.sock.recv(1)
if not c:
raise ConnectionError("connection closed")
length += c
n = int(length[:-1])
data = b""
while len(data) < n:
chunk = self.sock.recv(n - len(data))
if not chunk:
raise ConnectionError("connection closed")
data += chunk
return json.loads(data)
def send(self, name, params=None):
self.msg_id += 1
payload = json.dumps([0, self.msg_id, name, params or {}]).encode()
self.sock.sendall(str(len(payload)).encode() + b":" + payload)
while True:
msg = self._recv()
if msg[0] == 1 and msg[1] == self.msg_id:
break
_, _, error, result = msg
if error:
raise RuntimeError(error)
return result
mode = sys.argv[1] if len(sys.argv) > 1 else "text"
m = Marionette()
m.send("WebDriver:NewSession", {})
try:
if mode == "url":
print(m.send("WebDriver:GetCurrentURL")["value"])
elif mode == "title":
print(m.send("WebDriver:GetTitle")["value"])
else:
r = m.send("WebDriver:ExecuteScript",
{"script": "return document.body.innerText;", "args": []})
print(r["value"])
finally:
m.send("WebDriver:DeleteSession")
これを ~/.local/bin/page などに配置して chmod u+x ~/.local/bin/page などとした上でパスを通しておく。
たとえば、今 Firefox で表示しているページのタイトルを取得するには:
$ page title
Extracting data from Firefox on Ubuntu - Claude
ここでは Ubuntu Desktop を使用しているので、Desktop の左端にあるランチャー?(なんと呼ばれているかわからない)から Firefox を起動したときに marionette オプションを有効にしておきたい。
これは Ubuntu Desktop のお作法(Gnome のお作法なのかもしれない、よくわかってない)で、 ~/.local/share/applications/firefox_firefox.desktop に設定を所定の形式で書いておくと、そのランチャーから Firefox を起動するときの 振る舞いを変更できる(上書きできる)らしい。
デフォルトのスクリプトは /var/lib/snapd/desktop/applications/firefox_firefox.desktop にあるので、それを コピーして ~/.local/share/applications/firefox_firefox.desktop に配置して、 そのスクリプト内の /snap/bin/firefox を /snap/bin/firefox --marionette に置換しておけばよい。
起動スクリプトのコピー:
mkdir -p ~/.local/share/applications
cp /var/lib/snapd/desktop/applications/firefox_firefox.desktop ~/.local/share/applications/
sed で置換:
sed -i 's|/snap/bin/firefox|/snap/bin/firefox --marionette|' \
~/.local/share/applications/firefox_firefox.desktop
sed って 普通 s/A/B/ みたいに使うけど、セパレータに / を使う代わりに | を使うこともできるんだね(初めて知った)。 もし / をセパレータとして使うと、置き換え文字列に出現する / をエスケープしないといけないから、とても煩わしい。
以前のエントリー AppleScript を使って Safari から情報を得る 【Emacs 編】 と ほぼ同じなので、簡単に書く。
scratch のバッファで、これ:
(defun my/get-title ()
(string-trim
(shell-command-to-string "page title"))
(defun my/insert-title ()
(interactive)
(save-excursion (insert (my/get-title))))
(global-set-key (kbd "C-c i") #'my/insert-title)
これで C-c i すれば、 emacs のバッファに今 Firefox で表示しているページのタイトルを挿入できる。
Any program running as your user can control the browser while Marionette is on. That includes reading pages where you're logged in.
常時 Marionette 付きで Firefox 起動しているから、このマシンのユーザーは誰でも Firefox の内容にアクセスできてしまう。 自分しか使わないマシンだったらほぼ問題ないけど、 最近は AI もそこにいる場合があるから注意が必要。