1仕組みと動作原理
一時的なブラウザインスタンスではなく、patchright(Playwrightの検出回避フォーク)を使用して**実際のChromeの永続ユーザープロファイル**を起動します。これが複数回呼び出しにわたって「ログイン状態」を維持できる基盤となっています。
channel="chrome", # Use real Chrome
認証フェーズでは表示可能なブラウザを開いて手動ログインを待ち、cookies + localStorage を state.json に保存します。この一連のフローの認証情報は API キーではなくこのファイルです。
context.storage_state(path=str(self.state_file))
実行時に state.json のクッキーを手動でブラウザコンテキストに注入し、Playwrightの「セッションクッキーが user_data_dir に書き込まれない」既知の問題を回避します。
context.add_cookies(state['cookies'])
質問ごとに「1問につき1ブラウザセッション」として実行されます:新規ページを開く → ユーザー指定の notebook URL を開く → DNS レベルのホワイトリスト待機(ログイン画面にリダイレクトされていないことを確認するため、notebooklm.google.com ドメインへの復帰のみを許可)。
page.goto(notebook_url, wait_until="domcontentloaded")
質問テキストは「人間らしい入力」で textarea に1文字ずつ入力され、3段階のセレクタフォールバック(ドイツ語の aria-label を含む)を備えています。入力ボックスの検出に失敗すると処理全体が失敗します。
"textarea.query-box-input", # Primary
回答の取得はポーリングによる安定性判定で行われます:`div.thinking-message` の消失を待ち、レスポンスコンテナの最後の要素のテキストを取得し、複数回連続で一致した場合にのみ回答完了と判定します。
thinking_element = page.query_selector('div.thinking-message')
スクリプトは stdout に返す前に、回答テキストの後ろに Claude 向けの指示文を強制的に結合し、「必ず追質問を継続する」閉ループを形成します。
return answer + FOLLOW_UP_REMINDER
run.py は公式に唯一推奨されているエントリポイントです:.venv が存在しない場合はシステム Python で setup_environment.py を実行してブートストラップし、その後 venv インタプリタで対象スクリプトを実行します。
result = subprocess.run([sys.executable, str(setup_script)])
notebook ライブラリは純粋なローカル JSON メタデータ(url/name/description/topics/use_count)であり、ベクトルストアやコンテンツキャッシュはありません。「グラウンディング」は実際にはローカルではなく Google 側で行われます。
self.library_file = self.data_dir / "library.json"
2コア機能
3外部依存関係
| Kind | Dependency / Endpoint |
|---|---|
| network | Google NotebookLM 站点(浏览器自动化目标) |
| network | 提问页 URL 白名单校验(确认未被重定向去登录) |
| network | Google 账号登录态判定(字符串检测,非主动请求) |
| package | patchright(Playwright 反检测分支,浏览器自动化核心) |
| package | python-dotenv(声明为依赖,但代码从未使用) |
| cli | pip 安装依赖(走默认 PyPI) |
| cli | 下载安装 Google Chrome 二进制 |
| cli | 另一条安装路径装的是 chromium(与上一条不一致) |
4推奨統制措置と判定根拠
- SKILL.md / 脚本参数: 自動化検出の回避、ホストサンドボックスの無効化、または SSL 証明書検証のスキップを含む
- SKILL.md / 会话存储: ブラウザのユーザーログイン状態およびセッション Cookie を読み取りまたは再利用する
- 本地凭据 / 浏览器配置: ユーザーのログイン Cookie/セッション/キーチェーンの読み取り: ブラウザプロファイル内の Cookie データベースは Chrome 自体によって読み書きされる(user_data_dir は <skill>/data/browse を指定)
- scripts/: ローカルスクリプトまたはコマンドの実行: run.py は .venv が存在しない場合にシステムインタプリタで setup_environment.py を実行する: `result = subprocess.run([sy
- scripts/ 或 SKILL.md: 外部言語パッケージ依存関係の動的インストールを宣言
- 网络端点: 外部ネットワークアクセスの宣言: ブラウザ自動化による Google NotebookLM へのアクセス: `page.goto("https://notebooklm.google.com", wait
- 本地工作目录: ファイルの読み書きと成果物の出力: state.json(すべての Google セッション Cookie を含む)の書き込み: `context.storage_state(path=str(self.st
5二重目の独立検証
- [ok] skill.path = '.'(根级 SKILL.md) — 重读 SKILL.md L1-4 确认 frontmatter 位于仓库根文件;glob 根 *.json 无命中(无 plugin.json / marketplace.json),故技能入口就是仓库根。
- [ok] official_desc 逐字 — 重读 SKILL.md L2-4:name: notebooklm、description 为单行完整句,与 README L15 的同一句(README 用连字符 'Drastically reduced hallucinations - answers only from your uploaded documents.')措辞略异,已按 frontmatter 原文收录。
- [ok] 混合认证机制(persistent profile + state.json 注入) — 重读 browser_utils.py(launch_persistent_context 与 `context.add_cookies(state['cookies'])`)与 auth_manager.py(`context.storage_state(path=str(self.state_file))`),行号与首遍一致;AUTHENTICATION.md 的说明标注的脚本行号与实码相差数行(文档漂移),机制描述本身正确。
- [ok] 安全结论:反检测与沙箱关闭 — 重读 config.py 的 BROWSER_ARGS 列表:`'--disable-blink-features=AutomationControlled', # Patches navigator.webdriver` 与 `'--no-sandbox',` 逐字确认;重读 requirements.txt 首段注释确认 'anti-detection' 表述与 patchright pin。三条红色判据均在源码可定位。
- [ok] 安全结论:凭证读取范围 — 独立重扫 os.environ|getenv|API_KEY|token|keychain|.env|ssh|credentials:scripts 下零命中(唯二 token 字样在 requirements.txt 与文档中的 python-dotenv)。凭证只有 state.json 里的 Google cookie,路径由 config.py 常量推导,无 ~/.claude 硬编码。
- [ok] 安全结论:网络外发范围 — 重扫 requests|urllib|socket|http.client 于 scripts:零命中;网络只经浏览器(notebooklm.google.com / accounts.google.com)、pip(PyPI)与 patchright 下载 Chrome(域名不可定位,已记入 unlocated)。
- [ok] 安全结论:写盘与删除边界 — 重读 auth_manager、notebook_manager、cleanup_manager、__init__ 的写路径:state.json / auth_info.json / library.json / .venv,全部位于 <skill>/data 与 <skill>/.venv;删除限定在 data/ 且显式排除 .venv(`Virtual environment (.venv) is never deleted`)。
- [discrepancy] 宣称 vs 实际:citation-backed — 脚本内无任何 citation/来源条目的解析代码,唯一取数路径是响应容器最后一元素的 inner_text;README L65 与 SKILL.md 的 citation 表述实际描述的是 NotebookLM/Gemini 侧行为,本 skill 只做纯文本透传,不能保证引用随答案回到模型上下文。
6結論
edda31a0efaa9b1c…