Gemini API×RSS×launchdで朝夕2回のAI日報を全自動生成するMac一次情報リサーチ術
毎朝スマホを開いて SNS やまとめサイトを眺めていると、誰かのポジショントークや感情的な二次情報ばかりが目に入り、肝心の「世界で実際にどんな論文・特許・法律・予算が動いたのか」という一次情報になかなか辿り着けません。かといって海外の科学誌や公的機関のサイトを毎日手動で巡回するのは時間がいくらあっても足りません。
結論からお伝えすると、情報収集の質と時間を劇的に変える最適解は、「信頼できる一次情報の RSS フィードを Node.js で直接集め、Gemini API と macOS の launchd で毎日朝・夕 2 回、自分専用の分析レポートをローカルへ全自動生成する仕組み」 を組むことです。本記事では、スリープ復帰時の通信エラー対策からビルド破壊を防ぐ JSON 構造化出力まで、実稼働コードをベースに解説します。
-
【Google AI Pro vs Ultra徹底比較】月額2,900円と36,400円の損益分岐点と賢い使い分け : 定額サブスクリプションと従量課金 API をどう組み合わせると最もコスト効率が良いかを検証しています。
-
【Gemini 4 Carbon vs Argon徹底解剖】コードネーム『Fairwind』の正体と次世代AIモデルの賢い選び方 : 分析・推論タスクで圧倒的な精度を発揮する最新 Gemini 4 世代のモデル特性を詳しく解説しています。
-
【16GB RAMDisk 爆速化術】64GBメモリの余剰でSSD寿命を守りビルドを30秒で終わらせる設計 : 定期実行スクリプトの一時領域(
TMPDIR)をメモリ上へ逃がして SSD の摩耗をゼロにする基盤設計です。 -
【GitHub Actions無料枠パンク脱出録】『2秒でFailed』と.npmrc混入エラーを解決し、macOS標準『launchd』で完全無料の自動実行基盤を作った全記録 : 非公開リポジトリでGitHub Actionsが『Failed in 2 seconds』で止まる無料枠の壁と.npmrc混入クラッシュを乗り越え、macOS標準のlaunchdでスリープ復帰補完・Wi-Fi待機付きの完全無料自動実行へ移行した手順を解説します。
-
Gemini API・Google AI Studio従量課金の罠|2万円先払い検証とKVキャッシュの仕組み : 定額制限の回避を狙ってGoogle AI Studioへ2万円先払いチャージしGemini APIを使った実体験レビュー。429レート制限やWeb版より精度が落ちる原因、入力最大90%割引のKVキャッシュとHBM・DRAM・SSDの仕組みを解説します。
-
SNS のノイズや扇情的なまとめ記事に疲れており、海外論文・特許・公的機関の一次情報だけを毎朝スッキリ把握したい 方
-
Gemini API と Node.js を使い、自分のブログや研究テーマに直結する「下書き(たたき台)」まで自動で用意させたい 方
-
Mac の
launchdで定期スクリプトを組んだものの、スリープ復帰直後のネットワーク切断エラーやnvmのパス問題でつまずいた 方
SNSの二次情報疲れを断つ自分専用AI朝刊・夕刊
世の中の AI ニュース要約サービスや Web 上の定期タスク機能は便利ですが、情報源が一般的なニュースサイトに偏っていたり、要約結果がチャット画面の中に閉じ込められていたりするのが難点です。ローカルの Mac 上で RSS 巡回と Gemini API を直結させると、自由度と資産性が桁違いに高まります。
| 比較項目 | 手動での SNS・ニュース巡回 | クラウド AI の定型スケジュール機能 | RSS × Gemini API × launchd(本方式) |
|---|---|---|---|
| 情報源の純度 | 煽りや感想・二次情報が混ざりやすい | 検索エンジンの上位記事に引っ張られる | 自分が厳選した論文・公的機関 RSS 100% |
| 保存先と検索性 | 流れて消える(あとから探せない) | 各 AI サービスの画面内に分散する | 手元の Markdown フォルダ&SQLite に永久蓄積 |
| 次工程への直結 | ゼロから自分で構成を考えて書く | コピペして書式を手直しする手間が発生 | そのまま公開昇格できる MDX 下書きまで自動生成 |
| スリープ時の挙動 | — | クラウド側で実行される | Mac を開いた瞬間に launchd が自動補完実行 |
朝起きてコーヒーを淹れとる間に、世界中の最新の論文や法改正が日本語のレポートになって手元のフォルダに届いとるわけじゃな。記者の感想文を全部カットして「数字と事実と出典 URL だけ出せ」と指示できるのが最高じゃわい。
まさに「自分専用の調査室」を Mac の中に持つ感覚ですね!しかも出力先を Astro サイトの非公開フォルダ(hidden: true)にしておけば、AI エディタからも即座に全文検索して執筆の根拠データとして使えるんです。
一次情報RSS×Gemini API自動生成の全体像
論文・特許・法制を直結する12系統RSS設計
どんなに優秀な AI モデルを使っても、入力する材料(ゴミデータ)が悪ければ出力も薄っぺらくなります。そこで巡回対象の RSS リストには、ゴシップや一般コラムを含まない「科学論文・知財・国際機関・技術コミュニティ」を中心に 12 系統を登録し、直近 24 時間以内に公開された記事だけを抽出しています。
Nature、arXiv、IPWatchdog、EU議会、IMF、国内行政動向などから最新記事を収集します。
Gemini APIで記者の主観を排除し、統計・予算額・法案の一次事実のみを出典付きでレポート化します。
記事化すべき重大テーマがあれば、JSONスキーマ指定で各章のパーツを抽出します。
公開ディレクトリを汚さず、hidden: true 付きのMD/MDXとして内部資料フォルダへ安全保管します。
モデル呼び出し部(generateWithArgonOnly)では、下位モデルや旧世代モデルへ安易に自動フォールバックさせると分析の鋭さが落ちたり引退済みモデルへのリクエストで無駄なエラーを招いたりするため、使用するモデルは最上位の gemini-4-argon 一択に完全固定 しています。スリープ復帰直後のネットワーク瞬断(fetch failed)や一時的な API 混雑(HTTP 429 / 503 エラー)が起きた場合も、他モデルへ妥協切り替えせず DNS 疎通の再確認と指数バックオフ待機(12 秒 → 25 秒 → 45 秒)を挟んで gemini-4-argon 単体で粘り強く再試行する安全網を組んでいます。
MDX構文破壊を防ぐJSON構造化テンプレート合成
この自動生成システムを運用する中で一番の学びになったのが、「AI に直接 .mdx ファイル全文をフリーテキスト出力させてはいけない」 という教訓です。
Astro の MDX コンパイラは構文に非常に厳格です。AI に Markdown や MDX を丸ごと書かせると、YAML フロントマターの references 内にコロン(:)が混ざってパースエラーになったり、見出しに勝手な番号や ** が入って目次ルールから外れたりする事故が一定の確率で起きます。
- YAMLフロントマター内の引用符抜けやコロン混入でビルドが停止する
- 見出しの文字数上限(30文字)や禁止記号のルールを時々破る
- コンポーネントの import パスや閉じタグを書き間違えるリスクがある
responseMimeType: “application/json”で各章の本文テキストだけを受け取る- フロントマターは
JSON.stringify()で100%安全にエスケープする - 見出しは
sanitizeHeadingSuffix()で記号除去と文字数切り詰めを機械保証する
具体的には、以下のように AI からは純粋な JSON オブジェクトのみを受け取り、JavaScript 側のテンプレート関数で安全な MDX へ組み立てています。
// 見出しサフィックスから禁止記号を除去し、文字数上限以内に収める機械ガード
function sanitizeHeadingSuffix(rawSuffix, fallbackText, prefixLength = 3, maxTotalLength = 30) {
let s = String(rawSuffix || "")
.replace(/\r?\n/g, " ")
.replace(/\*\*/g, "")
.replace(/<\/?[a-zA-Z][^>]*>/g, "")
.replace(/\{[A-Za-z0-9_$.]+\}/g, "")
.replace(/^(?:\d+[\.\))\s::]|[①-⑳]|■|◆|●|▼|▶)+/, "")
.trim();
if (!s) s = fallbackText;
const maxChars = Math.max(8, maxTotalLength - prefixLength);
const chars = [...s];
return chars.length > maxChars ? chars.slice(0, maxChars).join("") : s;
}
// Gemini API 呼び出し時は JSON MIME タイプを指定して構造化データのみを受け取る
const rawResp = await ai.models.generateContent({
model: "gemini-4-argon",
contents: prompt,
config: {
responseMimeType: "application/json",
thinkingConfig: { thinkingLevel: "high" },
},
});
この「AI には中身の論理と文章だけを考えさせ、器(構文・フロントマター・タグ)は決定論的なコードで組む」という役割分担にして以降、ビルドエラーは完全にゼロになりました。
Macのlaunchdで毎日2回安定稼働させる急所
スリープ復帰直後のDNS失敗を防ぐ60秒待機処理
定期実行のスケジューラには、昔ながらの cron ではなく macOS 標準の launchd(~/Library/LaunchAgents/*.plist) を使います。最大の理由は、夜間や外出中に Mac をスリープさせていても、スリープから復帰した瞬間に「寝ている間に逃したスケジュール分」を自動で補完実行してくれる からです。
ただし、ここに Mac 特有の有名な落とし穴があります。Mac の画面を開いてスリープから復帰した直後の数秒間は、まだ Wi-Fi や有線 LAN の再確立が終わっておらず、launchd が即座に Node.js スクリプトを走らせると ENOTFOUND(DNS 名前解決エラー)で即死してしまう のです。
「手動でコマンドを打つとちゃんと動くのに、朝 Mac を開いたときの自動実行だけ毎回エラーログが出ている!」という現象の正体はそれだったのね!
大正解です!スクリプトの冒頭に、Google API サーバーの名前解決が通るまで 3 秒おきに最大 60 秒間じっと待つ waitForNetwork() を 1 つ挟むだけで、スリープ復帰直後の失敗がピタッとなくなりますよ。
import dns from "node:dns/promises";
const sleep = (ms) => new Promise((resolve) => setTimeout(resolve, ms));
// スリープ復帰直後のWi-Fi/LANリンク確立を最大60秒待機するガード
async function waitForNetwork(maxRetries = 20, intervalMs = 3000) {
for (let i = 1; i <= maxRetries; i++) {
try {
await dns.lookup("generativelanguage.googleapis.com");
return true;
} catch {
console.log(`[Network] 接続待機中... (${i}/${maxRetries})`);
await sleep(intervalMs);
}
}
return false;
}
3時間クールダウンとnvm絶対パス指定の鉄則
さらに毎日気持ちよく動かし続けるために、以下の 3 つの工夫を .plist とスクリプトの双方に入れています。
-
実行時刻は「00分ちょうど」を避けて朝
06:17・夕方18:23に散らす : 世界中のボットやバッチ処理が集中する毎時00分や30分は、RSS 配信元サーバーも Gemini API も一時的な混雑(503エラー)を起こしやすくなります。中途半端な分(17分や23分)にずらすだけで成功率がぐっと安定します。 -
3 時間の重複実行クールダウンを入れる : 朝と夕方の両方とも逃していた場合やプロセス再読み込み時に、数秒差で連続実行されて API 枠を無駄遣いしないよう、出力先ファイルの更新時刻(
mtimeMs)を確認し、「直近 3 時間以内に生成済みならスキップする(手動強制実行は--force)」 というガードを入れています。 -
nvm環境の Node パスと.envは必ず絶対パスで明示する :launchdはターミナルの.zshrcを読み込まないため、nodeとだけ書くと「コマンドが見つかりません」になります。which nodeで調べたフルパスをProgramArgumentsに記述し、スクリプト側でもpath.join(__dirname, '../.env')で環境変数を確実にロードします。
実際に使用している LaunchAgent 設定ファイル(パスは汎用表記)は以下の通りです。朝刊で海外の深夜動向をキャッチし、夕刊で国内の最新発表を上書き更新する 1 日 2 回体制が最もリズムよく機能しています。
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>Label</key>
<string>com.example.daily-ai-news</string>
<key>ProgramArguments</key>
<array>
<string>/Users/yourname/.nvm/versions/node/v24.20.0/bin/node</string>
<string>/Users/yourname/Desktop/my-blog/scripts/generate_daily_ai_news.js</string>
</array>
<key>WorkingDirectory</key>
<string>/Users/yourname/Desktop/my-blog</string>
<key>StartCalendarInterval</key>
<array>
<dict>
<key>Hour</key>
<integer>6</integer>
<key>Minute</key>
<integer>17</integer>
</dict>
<dict>
<key>Hour</key>
<integer>18</integer>
<key>Minute</key>
<integer>23</integer>
</dict>
</array>
<key>StandardOutPath</key>
<string>/tmp/daily-ai-news.log</string>
<key>StandardErrorPath</key>
<string>/tmp/daily-ai-news.err.log</string>
<key>ProcessType</key>
<string>Background</string>
</dict>
</plist>
みんなが押し寄せる 00 分を避けて 6 時 17 分にこっそり新聞を取りに行くなんて、賢い早起き猫のワザでちね!
まとめ:情報の受け手から一次情報の分析者へ変わる
毎日流れてくる大量のニュースを自分の目と指で追いかけ続けるのは限界がありますが、集める場所(一次情報 RSS)と分析の軸(プロンプト)さえ自分で設計してしまえば、AI は 365 日休まず働く優秀な専属リサーチャーになってくれます。まずはあなたの関心分野の RSS を 5〜10 個選び、毎朝 1 枚の Markdown 日報が自動で届く心地よさ を体験してみてください。
-
導入して幸せになる人 : 専門分野の最新論文・法改正・技術トレンドを出典付きで漏れなく把握し、ブログ執筆や研究開発のネタ帳を自動で育てたい Mac ユーザーの方
-
別の選択肢が向く人 : API キーの発行やターミナル設定を行わず、スマホアプリの手軽なニュース通知だけで十分な方
ご自身の Mac とブログ・ノート環境(Astro、Obsidian、Notion 用 Markdown など)に合わせてこの自動日報システムを構築したい方は、以下のプロンプトをコピーして AI エディタへ渡してみてください。
※launchd のパス解決や API レート制限・JSON スキーマ設計をミスなく一発で組ませるため、必ず 『Gemini 4 Argon』(または同等以上の最上位推論モデル)を選択して実行してください。
以下の記事の設計にもとづき、私の Mac 環境に「一次情報 RSS × Gemini API × launchd による朝・夕2回の自動リサーチ日報システム」を構築してください。
参照URL: https://lab.chihouzakki.com/blog/review/gemini-api-rss-launchd-daily-research-automation/
【作業ルール(厳守)】
1. まず私の Mac の node 実行ファイルの絶対パス(which node)、保存したいフォルダ構成、.env の有無を確認し、実装計画と巡回したい RSS ジャンルの案を提示して私の合意を得てください。
2. スクリプトには必ず ①スリープ復帰直後のDNS待機処理(waitForNetwork)、②短時間の重複実行を防ぐクールダウン判定、③API使用モデルを gemini-4-argon 一択に固定した上での通信瞬断・混雑時の指数バックオフ再試行(下位モデルへのフォールバック禁止)、④構文エラーを防ぐ JSON 構造化出力(Structured Outputs)を組み込んでください。
3. API キーは絶対にコードへ直書きせず .env(.gitignore 対象確認必須)から読み込む設計とし、テスト実行(--force)で正常出力を確認してから launchd 登録手順を案内してください。 ノイズだらけのタイムラインから卒業して、澄み切った一次情報で 1 日を始める習慣を手に入れましょう!

▲ 朝起きたときにはもう、世界の動きが1枚のレポートに整理されています