Airbnb ホスト画面の閲覧数・成約率を、ログイン済みの常駐ブラウザから自動で読む(クリックなし・JSON 化)
ホスト実績ページ(閲覧数・成約率)を CDP の常駐ログイン窓から読み、掲載別の JSON にする手順。本文の4行構造・下位10件しか出ない表の詳細ページ補完・browser.close 禁止などの安全規則・実ページ本文を fixture にする検証まで
約3.6万トークンの節約 (API料金換算で約54円分)。 要件定義・技術調査・試行錯誤ぶんのトークンがまるごと不要になります。※ 出品者申告とレビューに基づく推定値。モデル・タスク内容により変動します。
この巻物について
「Airbnb ホスト画面の閲覧数・成約率を、ログイン済みの常駐ブラウザから自動で読む(クリックなし・JSON 化)」は、データ収集カテゴリのAI指示書(MDファイル)です。ホスト実績ページ(閲覧数・成約率)を CDP の常駐ログイン窓から読み、掲載別の JSON にする手順。本文の4行構造・下位10件しか出ない表の詳細ページ補完・browser.close 禁止などの安全規則・実ページ本文を fixture にする検証までこの巻物をAIに読み込ませると、ゼロから設計・調査する場合に比べて 約3.6万トークン(API料金換算で約54円)・80%のトークンを節約できます。
- カテゴリ
- データ収集
- 対応AI
- claude-code、cursor、codex-cli
- ライセンス
- 商用利用可 (再販不可)
- 価格
- 無料
- ゼロから開発時
- 約4.5万トークン
- この巻物使用時
- 約9,000トークン
- 節約量
- 約3.6万トークン (約54円)
- 更新日
- 2026-09-20
使い方 (AIに渡す3つの方法)
いちばん簡単なのはワンライナー。Claude Code のターミナルに貼るだけです。
claude "https://makimono-md.vercel.app/api/v1/files/airbnb-json/raw を読み込んで、この指示書どおりに実装して"
中身
Airbnb ホスト画面の閲覧数・成約率を、ログイン済みの常駐ブラウザから自動で読む(クリックなし・JSON 化)
目的と境界 人がログインした Chrome に CDP で接続し、実績ページの本文とリンクを読み取る。認証情報の入力や設定変更は行わない。取得できない値をゼロにせず、欠測と失敗理由を JSON に残す。
1. 接続する前に
対象のホスト実績を取得できる一般公開 API はないため、ログイン済みの画面を読む。人が専用プロファイルの Chrome を CDP 有効で起動し、ログインを済ませて常駐させる。CDP はローカル接続に限定する。
AI に渡すのは、Airbnb 専用と確認済みの CDP 接続先、出力先、対象掲載の対応表だけとする。パスワードや Cookie の値を指示書・ログ・成果物へ書かない。他サービスのポートを探索したり、接続失敗時に Chrome を起動したりしない。
使用ライブラリは Node.js と Playwright。既存の常駐窓管理ツールがある場合は、その接続先と生存確認方法を先に読む。
2. 読むページと本文の構造
閲覧数は /performance/conversion/p3_impressions、成約率は /performance/conversion/conversion_rate を読む。掲載単位の詳細は /performance/conversion/<metric>/listing/<listingId>。
観測した画面では /hosting/performance は 404、/hosting/insights はクオリティ画面へ転送された。実績の取得先には使わない。ただし画面構成は変わり得るので、本文の見出しも確認する。
一覧の本文には、全掲載ではなく下位10件だけが出る場合がある。「N件のリスティングを表示」は展開ボタンだが押さない。本文にない掲載は、事前に用意した掲載対応表を使い詳細ページで補う。総件数だけ分かっても、欠けた掲載の ID は推定できない。
本文は原則として1行1項目。表のヘッダは「リスティング名」「増減」「合計」、成約率では最後が「割合」になる。その後は公開タイトル、内部名、増減、値の4行を1組として読む。表の終端は ^\d+件のリスティングを表示$ で検出する。
増減には符号付き整数、符号なし整数、先頭空白付きの割合、欠測記号「—」がある。各行を trim しても、空行や欠測行を無条件で削除して4行の対応を崩してはいけない。行数や値の形式が合わなければ warning を出す。
上部 KPI は数値の次の行がラベルになる。ラベルを見つけ、その直前行を数値化する。期間は「N件のリスティングで、<from>~<to>の『…』は…」に相当する文から取り、更新日は「最終更新:」から取る。年が省略されている場合は原文を保持し、根拠なく年を補わない。
本文には名前と掲載 ID の対応がない。対象 metric の /performance/conversion/<metric>/listing/<数字> に一致する a[href] を DOM 順で集め、表の行と index で対応させる。件数不一致なら、その表の ID は null にして warning を残す。詳細補完には別途確認済みの掲載対応表を使う。
3. JSON と純関数の契約
最上位キーは date、measuredAt、window、summary、listings、warnings、errors、exitCode に固定する。
dateは指定タイムゾーンの計測日、measuredAtは ISO 形式の取得時刻。windowはfrom、to、lastUpdated、listingCount。summaryは平均閲覧数や平均成約率など、ラベルから取った KPI。listingsの各要素はname、publicTitle、listingId、views、viewsDelta、conversionRate、conversionDelta、sources。sources.viewsとsources.conversionRateはtable、drilldown、null のいずれか。増減も別に出所を持たせる。
欠測はすべて null。割合は % 単位の数として格納する。たとえば合成テスト値の 0.45 は 0.45% を意味し、小数比率へ変換しない。真のゼロは保存する。
次の純関数を export し、ブラウザ操作から分離する。
parseMetricNumber:空白、桁区切り、符号、% を処理し、欠測や不正値は null。parseTable:ヘッダと終端を検証し、4行ずつ解析する。parseSummary:ラベル候補配列で直前行を読む。parseWindow:期間、更新日、掲載数を抽出する。parseDrilldown:詳細のラベルと対象掲載を検証して値を読む。pairRowsWithLinks:件数一致時だけ ID を対応させる。merge:ID を主キーに統合し、欠測だけ補う。名前の曖昧一致で結合しない。
閲覧数の候補には「平均ページ閲覧数」、詳細には「合計ページ閲覧数」を使う。成約率は「全体の平均成約率」、詳細は「全体の成約率」。ほかに「検索1ページ目のインプレッション率」「検索からリスティング閲覧への平均コンバージョン率」「リスティング閲覧からの平均成約率」を扱い、「平均」の有無は候補配列で吸収する。
一覧と詳細の期間が違う値を混ぜない。期間を確認できない補完値は採用せず warning を残す。部分取得は exit 1、完全取得は exit 0、CDP 不通は exit 2 とする。
4. 実装骨格
以下は接続と取得の骨格。performance-parser.mjs に前節の純関数と、本文待機・認証判定・期間照合を行う補助関数を実装する。collect は本文とリンクを保存し、complete は未取得の掲載・指標を判定する。
import { chromium } from 'playwright';
import {
initial, collect, merge, complete, finish, loginWall
} from './performance-parser.mjs';
const cdp = process.env.AIRBNB_CDP_URL;
const known = JSON.parse(process.env.LISTINGS_JSON || '[]');
const metrics = ['p3_impressions', 'conversion_rate'];
const out = initial();
let page;
let stage = 'cdp';
async function read(metric, id = null) {
const suffix = id ? `/listing/${encodeURIComponent(id)}` : '';
const path = `/performance/conversion/${metric}${suffix}`;
await page.goto(`https://www.airbnb.jp${path}`);
await page.waitForLoadState('domcontentloaded');
if (await loginWall(page)) throw new Error('LOGIN_REQUIRED');
return collect(page, metric, id);
}
try {
const endpoint = new URL(cdp);
if (!['localhost', '127.0.0.1', '[::1]'].includes(endpoint.hostname))
throw new Error('LOCAL_CDP_REQUIRED');
const probe = await fetch(new URL('/json/version', endpoint), {
signal: AbortSignal.timeout(5000)
});
if (!probe.ok) throw new Error('CDP_UNAVAILABLE');
const browser = await chromium.connectOverCDP(cdp);
stage = 'read';
const context = browser.contexts()[0];
if (!context) throw new Error('CONTEXT_MISSING');
page = await context.newPage();
for (const metric of metrics) {
merge(out, await read(metric), 'table');
}
for (const listing of known) {
for (const metric of metrics) {
if (!complete(out, listing, metric)) {
merge(out, await read(metric, listing.listingId), 'drilldown');
}
}
}
finish(out, known);
} catch (error) {
out.errors.push({ code: error.message });
out.exitCode = stage === 'cdp' ? 2 : 1;
} finally {
if (page) {
await page.close().catch(() => {
out.warnings.push('OWN_TAB_CLOSE_FAILED');
if (!out.exitCode) out.exitCode = 1;
});
}
process.stdout.write(JSON.stringify(out, null, 2) + '\n');
process.exitCode = out.exitCode;
}
接続は connectOverCDP だけを使う。閉じるのは自分で作ったタブだけ。browser.close()、click、fill、type、press は書かない。ログイン壁では exit 1 にし、人に認証を戻す。process.exit() は使わず、finally の後に正常終了できる構造にする。接続が残る場合も共有 Chrome を閉じず、実行側でクライアントプロセスだけを管理する。
5. fixture と検証
fixture は保存した実ページの innerText から機械的に切り出す。人が記憶で書いたラベルを正解データにすると、「平均」の有無だけで本番が null になる。リンク順も同時保存する。
保存原本は非公開で管理し、公開用 fixture はタイトル・内部名・ID・日付・数値を機械的に置換する。行構造と欠測記号は保つ。欠測、真のゼロ、先頭空白、件数不一致、期間不一致を検証する。
- 実行前後に既存 keepalive の
--statusで常駐窓の生存を確認した。 - 認証必須ページを読んでログイン状態を確認した。
- JSON の null、warnings、errors、終了コードを確認した。
- 同じ期間のスクリーンショットと一覧・詳細の数値を照合した。
- 未表示掲載の補完と、既存タブが残っていることを確認した。
6. read-only のコーディングエージェントへ渡す
参照ファイル、呼び出し契約、匿名化した実ページ fixture は spec に全文同梱する。「既存ファイルを読めば分かる」で済ませない。
1 run = 2ファイルとし、たとえば解析モジュールとテスト、次の run で取得スクリプトと実行テストを作る。出力は各ファイル全文の FILE ブロックで受け取る。
保存後に node --check と node --test を実行する。さらに rg または grep で browser.close、click、fill、type、press、process.exit(、他サービスのポートや接続先の混入を検査する。静的検査だけで完了にせず、実走後のチェックまで行う。
よくある質問
+「Airbnb ホスト画面の閲覧数・成約率を、ログイン済みの常駐ブラウザから自動で読む(クリックなし・JSON 化)」とは何ですか?
ホスト実績ページ(閲覧数・成約率)を CDP の常駐ログイン窓から読み、掲載別の JSON にする手順。本文の4行構造・下位10件しか出ない表の詳細ページ補完・browser.close 禁止などの安全規則・実ページ本文を fixture にする検証まで
+どれくらいトークン(費用)を節約できますか?
ゼロから開発すると約4.5万トークンかかりますが、この巻物を使えば約9,000トークンで済みます。差し引き約3.6万トークン(API料金換算で約54円)・80%の節約です。
+どうやって使いますか?
無料です。MDファイルを Claude Code などのAIに読み込ませるだけ。ワンライナーをターミナルに貼れば実装が始まります。要件定義や技術調査を省いて実装だけにトークンを使えます。
+どのAIツールに対応していますか?
claude-code、cursor、codex-cli に対応しています。
+商用利用できますか?
ライセンスは「商用利用可 (再販不可)」です。
🤝 自分でAIを動かすのは、まだ不安…という方へ
この巻物の内容を、AIを使うプロに丸ごと任せることもできます。姉妹サービスAI代行堂なら「LINEで頼むだけで、仕事が完成」。
関連する巻物
定期スクレイピング→Googleスプレッドシート自動集計MD
競合価格・在庫・ランキングなどを毎日自動取得してスプレッドシートに蓄積するバッチを AI に作らせる指示書。robots.txt 尊重・レート制限・差分検知のベストプラクティス込み。
Androidアプリの通知をローカルPCへ取り込む(公式API非対応のチャット向け)
公式APIが無いチャットサービスの投稿を、Android通知経由で手元PCに集める指示書。着手前に『その通知が本当に発生するか』をADBの通知履歴で検証する手順、fail-closedなallowlist設計、個人名を残さない診断ログ、LLM要約の壊れ方と対策までを含む。
外部サイトの「異常」を報告する前に計測器を対照群で検定する
自社の掲載が検索に出ない・売切表示になる等を疑ったとき、対照群をツールに実装して測定不能をexit 2で止める手順。UA未設定で空ページを掴む罠、分母が列挙可能かの見方、履歴のない画面で「いつ落ちたか」を測らない原則つき。
この巻物、誰かのトークンも救えます
𝕏 で節約レシートをシェア