0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

Mac版KindleのページテキストをAIに読ませる

0
Last updated at Posted at 2026-08-19

統計学の本をKindleで買った。Claude Codeと一緒に読み進めたかったからだ。ページを開いて「読んで」と言えば要点をまとめてくれて、わからないところは噛み砕いてくれる。そういう読書がしたかった。

ブラウザ版Kindle(read.amazon.co.jp)で開ける本なら話は簡単で、ブラウザを操作できるAIならそのまま読んでくれる。ところが、買いたい本を無料サンプルで試したら「Kindleアプリが必要です」と断られた。本によってはブラウザ版で開けないのだ。

そこで、Macで動いているKindleアプリから表示中のページの本文を取り出す方法を探した。

結論から

Kindleアプリの本文は、アクセシビリティAPIから読める。 そこを読むSwiftを書いたら、表示中ページの本文がそのまま取れた。コード全文は後半に載せる。

なぜアクセシビリティAPIなのか。macOSにはVoiceOverという画面読み上げ機能があって、目の不自由な人はKindleの本を音声で読んでいる。読み上げができるということは、本文のテキストはアクセシビリティAPIを通って外に出ているということだ。同じ道を通れば、こちらからも読める。

動作確認した環境:macOS Ventura 13.6 + Amazon Kindle.app(Mac App Store版)

新しいmacOS(Sonoma・Sequoia)では試していないので、動くかどうかは分からない。ここで使うアクセシビリティAPIはVoiceOverの土台として長く同じ形で提供されているが、動作を保証できるのは上の環境だけだ。

先にやっておく準備

3つ済ませておくと詰まらない。

  1. Kindleアプリで本を開いておく。ライブラリ画面ではなく、本文が表示されている状態にする(ここで挙げるコードは、いちばん手前のウィンドウを読む)
  2. Xcodeのコマンドラインツールを入れるxcode-select --install を実行するとダイアログが出るので、完了するまで待つ(数分かかる。Xcode本体は要らない)。xcrun swift --version がバージョンを返せば入っている
  3. アクセシビリティの許可を出す。これは次の節で説明する

アクセシビリティの許可を出す

この記事のコードは、どれもアクセシビリティの許可がないと動かない(許可がないとエラーになるか、空の結果が返る)。

「システム設定 → プライバシーとセキュリティ → アクセシビリティ」を開いて、コマンドを実行するアプリをオンにする。ターミナルから直接実行するならTerminalやiTerm2、AIコーディングツールに実行させるならそのツールを動かしているターミナルアプリが対象だ。一覧に出てこないときは「+」ボタンで /Applications/ユーティリティ/ から手動で追加できる。許可を与えたらそのアプリを一度終了して開き直す

まずAppleScriptで試す

Kindleウィンドウの中にある全要素の value をかき集めてみる。ターミナルに貼り付けて、最後の EOF の行まで入れてEnterを押すと動く。

osascript <<'EOF'
tell application "System Events"
  tell process "Kindle"
    set out to ""
    repeat with e in (entire contents of window 1)
      try
        set v to value of e
        if v is not missing value and v is not "" then set out to out & (v as string) & linefeed
      end try
    end repeat
    return out
  end tell
end tell
EOF

出た。表示中の見開きの本文が、まるごと文字列で取れた。

⚠ ここで tell process "Kindle" としているアプリ名は、環境によって違うことがある。うまくいかないときは、アクティビティモニタでKindleのプロセス名を確認して置き換えてほしい。

ただし、この方法には弱点が2つあった。

  • 遅い。手元の実測で1.6秒、ページによっては数秒かかる
  • 不安定。要素の多いページだと、空の結果が返ることがある

Swiftで書き直す

AppleScriptが遅いのは、要素を1個たどるたびにSystem Eventsとのプロセス間通信が発生するからだ。同じことをアクセシビリティAPI(AXUIElement)で直接やれば、この行き来が消える。

次のコードを kindle_read.swift という名前で保存する。

import ApplicationServices
import AppKit

func axValue(_ el: AXUIElement, _ attr: String) -> AnyObject? {
    var v: AnyObject?
    AXUIElementCopyAttributeValue(el, attr as CFString, &v)
    return v
}

func walk(_ el: AXUIElement, _ out: inout [String]) {
    if let v = axValue(el, kAXValueAttribute as String) as? String, !v.isEmpty {
        out.append(v)
    }
    if let children = axValue(el, kAXChildrenAttribute as String) as? [AXUIElement] {
        for c in children { walk(c, &out) }
    }
}

guard let app = NSWorkspace.shared.runningApplications.first(where: { $0.localizedName == "Kindle" }) else {
    print("ERROR: Kindleアプリが起動していない"); exit(1)
}
let axApp = AXUIElementCreateApplication(app.processIdentifier)
guard let windows = axValue(axApp, kAXWindowsAttribute as String) as? [AXUIElement], let win = windows.first else {
    print("ERROR: Kindleのウィンドウが見つからない"); exit(1)
}
var out: [String] = []
walk(win, &out)
print(out.joined(separator: "\n"))

やっていることは3つだけ。

  1. 起動中のアプリ一覧からKindleを探し、そのプロセスIDを AXUIElementCreateApplication に渡して AXUIElement を作る
  2. いちばん手前のウィンドウから子要素を再帰的にたどる
  3. AXValue に文字列が入っていたら集めて、最後に改行区切りで出力する

毎回使うものなので、swiftc でビルドしておく。-O は最適化の指定で、外しても動くが起動が少し遅くなる。

xcrun swiftc -O -o kindle_read kindle_read.swift
./kindle_read

待ち時間はほとんど感じない。AppleScript版で起きていた「空の結果が返る」も、いまのところ起きていない。

出力はこうなる(『完全独習 統計学入門』のあるページ。長いので途中で省略した)。

0-6 リンク   リンク 数学記号も数学公式もほとんど使わない リンク 本書では、大胆に確率の部門をカットしたので、高校以上の数学を使う必要がなくなりました。他の統計学の教科書は、…
Kindle

たった2行しか出ない。見開き2ページぶんの本文が、まるごと1つの要素に入っているからだ。ページの中の見出しも段落も、Kindleは1個の大きなテキスト要素としてまとめて持っている。文中に混ざる「リンク」「画像」という単語は、目次へのリンクや挿絵があった位置に入っているように見えるが、Kindleが何を基準に入れているかまでは確かめていない。読むぶんには邪魔にならない。

2行目の Kindle は、ウィンドウ上部に出ている本のタイトル表示の要素で、本文ではない。

なお、ページによっては 位置No. 102 , 25% のような読書位置の行も一緒に出てくる。これも本文ではないが、あとで役に立つ。

ハマりどころ3つ

実際に使い込んで見つかった落とし穴を挙げておく。

  1. 取れるのは表示中のページだけ。続きが読みたければページをめくってもう一度実行する
  2. 図・イラスト・画像として埋め込まれた数式は取れない。テキストとして流れているものだけが対象だ。図が主役の本には向かない
  3. ページをめくった直後や表示を変えた直後は、前のページの内容が返ってくることがある。画面は進んでいるのに、取れる本文が1つ前のままになる。一緒に出てくる位置Noが画面下の表示とズレていたらこの状態だ。少し待ってもう一度実行するか、ページをめくり直すと直る

Claude Codeとつなぐ

ビルドしたバイナリを、消えない置き場所に移す。

mkdir -p ~/Library/Scripts
mv kindle_read ~/Library/Scripts/

あとは、この道具の存在をClaude Codeに覚えさせる。私はメモリに1行残したが、CLAUDE.md(Claude Codeが起動時に読む設定ファイル。~/.claude/CLAUDE.md に置けば全プロジェクトで、作業フォルダの直下に置けばそのフォルダでだけ効く)に書いても同じことができる。

Kindleアプリで表示中のページを読むときは ~/Library/Scripts/kindle_read を実行する

これで、本のページを開いて「このページ読んで」と言うだけになる(初回はコマンド実行の許可を1度聞かれる)。Claude Codeがコマンドを打ち、本文を読んで、要約や解説を返してくる。ページをめくって「次」と言えば、そのまま読み進められる。

他のアプリにも使えるか

他のアプリでは試していないので、同じ手が通るかは分からない。相手のアプリがどんな属性に何を入れているかは、Accessibility Inspector で覗ける。ウィンドウの上にカーソルを重ねると、その要素のRoleとValueがその場で表示されるので、kAXValueAttribute 以外に当たりがあるかを探すときに使える。

⚠ これはXcode本体に付属するツールなので、準備の節で入れたコマンドラインツールだけでは入らない。App StoreからXcodeを入れる必要がある。

おことわり

この方法で取れるのは、自分のアカウントで買った本の、いま画面に表示している1ページぶんのテキストだけだ。私の用途は「買った本をAIと一緒に読む」という読書補助で、この記事もその範囲を想定している。

取り出したテキストを保存して溜めること、配布すること、本をまるごと別の形にすることはしない。著作権の問題になるし、Kindleストア利用規約にも目を通したうえで、自分の読書の範囲で使ってほしい。

まとめ

  • Kindleアプリの本文は、VoiceOverが読み上げるのと同じアクセシビリティAPIから取れる
  • AXUIElement を直接たどるSwiftを1本書いておけば、表示中ページの本文がコマンド1回で取れる(AppleScriptでも取れるが1.6秒かかり、空振りすることがある)
  • 取れないもの(図・画像の数式)と、表示が固まったときの直し方(ページを1回めくる)だけ覚えておけば、日常の読書ツールとして使える
  • 自分が買った本を自分で読むための道具として使うこと
0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?