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?

ある日突然、Google Discoverが出なくなって詰んだのでなんとかした!

0
Last updated at Posted at 2026-10-19

この記事は、Claude Code(AI)の協力で調査と実装、文書化を進めたものです。何を作るかの判断と、実機での確認は筆者が行いました。

きっかけ

このシステムを作ろうと思ったのは、私の環境で、Google Discover がある日突然、見られなくなったからです。いつも見ていたのは、PC のブラウザで google.com を開いたときに、検索ボックスの下に出る記事の一覧です。Mac でも Windows でも、Chrome でその一覧が出なくなりました。情報収集の一部としてかなり有効に機能していたので、私にとって Google Discover が見られなくなったのは、かなり痛手でした。しかし、同じ Google アカウントでも、Android 端末の Chrome では、Discover が今も出ているという、よくわからない状態になっていることに気がつきました。

調べてみると、同じ症状の報告は 2026 年 9 月ごろから、X やブログに複数ありました(例: Zenn の解説、LifeTools Lab の調査、英語では Always Evolving SEO、X の投稿は英語と日本語の例)。PC 版の Chrome や Edge で記事一覧が消え、検索設定の「ホームページに Discover を表示」の項目まで無くなる、という内容です。原因は、Google から説明が出ていないので分かりません。「PC 向けの実験機能がサーバー側で止められたらしい」という伝聞は見つかりましたが、確かめられていません。復活させる設定や手順は、公式には見当たりません。ネットで見つかる対処法は、私も一通り試しましたが、戻りませんでした。非公式の URL で表示させる方法は、紹介していたブログ自身が、追記で使えなくなったと書いています。代わりに Google ニュースの「おすすめ」ページをホームに設定する案も、別のブログにありました。

PC では戻せなかったので、Discover が出ている Android 端末の Chrome を観測の窓口にして、表示された内容を自分で保存し、見られるようにすればよい、というのが出発点です。

Google Discover には公開 API がありません。しかもフィードはアカウントごと、端末ごとに個人化されます。自分に何が推薦されているかを確かめる手がかりは、端末に実際に表示された内容だけです。そこで、1 万円前後の格安の Android タブレットを「センサー」にして、表示されたフィードを ADB で読み取り、保存して、Web UI で見られるようにしました。この記事は、その作り方と、実機で分かったことの記録です。コードは GitHub のリポジトリに置いていますが、非公開です。この記事には、必要な部分を書いています。

測ったことと測っていないことは分けて書きます。再現率と精度は測っていません。

用語

用語 意味
Discover Google が個人向けに出す記事の推薦フィード(Google 検索ヘルプ、Search Central の解説)
ADB Android Debug Bridge。USB 越しに端末を操作するコマンド(公式ドキュメント)
UI 階層 uiautomator dump が返す、画面の要素の木構造(XML)。UI Automator は公式ドキュメントを参照
content-desc 要素に付くアクセシビリティ用の説明文
指紋 重複排除のために、見出しなどから作るハッシュ値

作ったもの

端末に表示されたフィードを読む、という方針にしたのは、推薦そのものを作り直しても、特定の利用者に実際に出た内容は再現できないからです。

言い換えると、自分のアカウントに出ている表示を、横から取ってくる仕組みです。Google のサーバーに直接アクセスすることも、通信を傍受することも、アプリを改造することもしません。端末の画面に出ている内容を、アクセシビリティの情報として読むだけです。

構成は次のとおりです。

システム構成

  • Android タブレット(TECLAST P30T、Android 16)を Raspberry Pi に USB でつなぎます。私のふだんの Google アカウントでログインしてあります。専用のアカウントを作ると、検索や閲覧の履歴がなく、個人化されていないフィードしか出ないので、観測したい「自分に出ているフィード」になりません。
  • Pi で、systemd のタイマーが毎正時(8:00 から 23:00 まで)に収集を走らせます。
  • 収集したレコードだけを、ssh トンネル経由で、別の VPS のコンテナ(FastAPI と SQLite)に送ります。生の XML とスクリーンショットは Pi の外に出しません。
  • ブラウザからは、ssh -L でトンネルを張って見ます。公開ポートは開けていません。

Web UI は白基調のタイル表示で、表示、クリック、滞在時間を記録します。あとでレコメンドの学習に使う予定です。レコードは、届いてから 24 時間で消えます。

Web UI

画面は、動作を確かめるためのダミーデータです。実際のフィードの内容は載せていません。

実機で分かったこと

Pixel のようなスマートフォンでなくても、1 万円前後の格安タブレットで足りました。実機に当ててみて、最初の想定と違った点が四つあります。

Discover は Google アプリではなく Chrome の新しいタブに出る

この端末では、Google アプリを開いても検索画面が出るだけでした。Discover は Chrome の新しいタブ(chrome://newtab/)に表示されます。起動は、パッケージ名だけでは解決せず、アクティビティを明示した intent で開きます。

adb shell am start -n com.android.chrome/com.google.android.apps.chrome.Main \
  -a android.intent.action.VIEW -d chrome://newtab/

見出しは content-desc にしか出ない

uiautomator dump の結果を調べると、見出しはどの text 属性にも入っていませんでした。各カードの共有ボタンとカードメニューのボタンの content-desc にだけ、次の形で出ます。

<見出し> を共有
<見出し>のカードメニュー

広告は Ad's title: …, from: … の形です。提供元、経過時間、記事の URL は、階層に出ません。このため、パーサーはこの二つのラベルの語尾だけでカードを見分けます。それ以外の画面上の文字は、何であれ記事として保存しません。日本語ロケールの語尾に依存しているので、他のロケールでは動きません。

開き直してもフィードは古いまま

最初の数時間、収集の結果が new=0 のまま変わりませんでした。原因は、intent で新しいタブを開いても、既存のタブが前面に出るだけで、古いフィードと前回のスクロール位置(末尾)が残っていたことです。毎回、同じ末尾の 6 枚ほどを読み直していました。

下に引っ張っても更新されません。Chrome の再読み込みボタンを押すと、フィードが新しくなり、位置も先頭に戻ります。収集の前に、そのボタンを押すようにしました。直したあとの 1 回は、10 回のスクロールで 70 件を読み、52 件が新規でした。

画面は横向きで、座標はダンプから取る

wm size は 800x1280 と答えますが、実際の表示は横向きの 1280x800 でした。スクロールの座標は、ダンプの最上位の要素の範囲から計算します。

収集の流れ

収集の流れ

ダンプ、解析、スクロールを、新しいカードが出なくなるか、10 回に達するまで繰り返します。重複は、NFKC で正規化した見出しと提供元の SHA256 で判定し、SQLite に UNIQUE 制約で入れます。

カードの画像を切り出す

見出しだけの一覧は読みづらかったので、スクリーンショットからカードごとの画像を切り出しました。実装で迷ったのは、どのカードを切り出してよいか、という判定です。

カードの高さは見出しの長さで変わるので、高さでは判定できません。最初に試した「高さが最大の 9 割以上」は、広告が最大値を引き上げてしまい、1 枚も切り出せませんでした。代わりに、次の規則にしました。

  • カードの外枠の上端が、Chrome のツールバーの下端以下にあること。ツールバーはフィードの上端に重なって描かれます。
  • 外枠の下端が、スクロール領域の下端に接していないこと。切れているカードは、ちょうど下端で終わります。

共有ボタンとメニューボタンは、切り出した画像の上で、カードの背景色で塗りつぶします。画像は Pillow で JPEG(幅 520 まで、品質 72)で、1 枚 15 kB ほどです。

提供元と時刻を Google ニュースの RSS で補う

フィードから提供元と記事の URL は取れません。そこで、公開されている Google ニュースの RSS 検索に、見出しを投げます。API キーも費用も要りません。見出しが十分に似ている(difflib の比が 0.92 以上)ときだけ採用し、提供元、公開時刻、同じ話題を載せた他の媒体の見出しを足します。ある回の 40 件では、29 件が一致しました。

本当の要約は取れません。説明として出せるのは、関連する見出しの一覧で、空のことも多いです。

ビューアの守り方

ビューアは自分用です。それでも、VPS を他のサービスと共有しているので、次のように絞りました。

  • コンテナは(Docker のセキュリティ)、読み取り専用のルート、非 root、cap_drop ALL、メモリ 256 MB、ポートは 127.0.0.1:8820 だけにしました。
  • アップロードには専用の ssh 鍵を使います。authorized_keys には (sshd(8) の authorized_keys の書式) restrict,port-forwarding,permitopen="127.0.0.1:8820",command="/usr/sbin/nologin" を付けました。restrict だけでは、コマンドの実行が許されたままでした。実際に試して分かり、command= を足して、シェルが拒否されることを確かめ直しました。
  • アプリは、Host ヘッダーが localhost 系のときだけ受け付けます(DNS リバインディング対策)。CSP はリクエストごとのナンスで出し、画像は自分のオリジンからだけ許します。
  • 点検では、トークンがリポジトリ、履歴、ログ、プロセスの引数に出ていないこと、8820 が外から届かないことを確かめました。

運用してみて

  • サーバーは 109 件を持ち、うち 48 件に画像、50 件に提供元が付いています(ある時点の数字です)。
  • 画像が付かないカードがあるのは、スクロールの途中で見切れていて、全体が一度も画面に入らなかったからです。
  • 更新は、サーバーを先、収集側を後にします。逆にすると、古いサーバーは画像を無視するのに、収集側は送信済みとして印を付けてしまいます。

注意と限界

  • 個人用の実験です。収集は 1 時間に 1 回、日中だけにしています。他人に提供する用途は想定していません。Google の画面を自動で操作する行為が、利用規約に照らして問題にならないかは、各自で確認してください。
  • 記事の URL は取っていません。カードをタップすると、フィードの学習が変わるおそれがあるためです。Web UI でタイルを押すと、見出しの Google 検索を開きます。
  • Chrome や Google の画面が変わると、パーサーが壊れます。カードが 1 枚も取れないときは、スクリーンショットと XML、アクティビティのダンプを残して失敗にし、任意の文字を記事として保存しないようにしています。
  • 再現率と精度は未測定です。テストは、実機のダンプを使った回帰用のものを含めて 47 件です。

今後

収集側の DB の保存期間、再現率の測定、他のロケールへの対応を考えています。Web UI が記録するクリックと滞在時間を使った、簡単なレコメンドも試したいと思っています。

参考

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?