英語の技術ニュースは追いきれない。自分の場合は Laravel News(Laravelの公式ニュース。英語で、ほぼ毎日更新)で、追える時と追えない時の差が激しく、どこまで読んだか分からなくなる。そこで Claude Code で収集を自動化して、2026年1〜6月の記事を日本語訳して手元にアーカイブし、出典リンク付きの月次まとめ6本を公開した(末尾にリンク)。
全て出典のリンクを貼っているので、気になる内容があればすぐに開ける

作ったもの
中身は Claude Code のスキルで、役割で3つに分けた。本文抽出は既存のスキルを借り、残り2つは自分の用途に合わせて作った。といっても、そのスキル(指示書)も手では書かず、Claude Code と対話して作った。sitemap の列挙や最後のチェックといった決定的にやりたい所は、小さなスクリプトに固定してある。
-
本文抽出(
web-content-extraction):URLを安全に取得して本文だけ Markdown にする前処理。Claude Code Starter Kit(Cloud Native Inc./MIT License)のスキルをそのまま使わせてもらっている。 -
収集とアーカイブ(
laravel-news-catchup):sitemapで列挙し、本文を取得して翻訳し、検証して索引にする。 -
記事化(発信)(
laravel-news-monthly-roundup):翻訳アーカイブから、月1本のまとめを書く。目玉のリリースはコード付きで深掘り、パッケージはテーマ別に厳選、残りは網羅リンクで拾う。仕上げに3観点(技術精度/日本語/作法)の並列レビューと、網羅/除外/UTM の決定的チェックを通して下書きに残す。
この3つは対等に並ぶのではない。本文抽出と収集とアーカイブは実行時に密結合した1つのエンジンで(図の実線)、記事化は全文訳アーカイブ(translations/)というファイルを読むだけの疎結合な下流だ(点線)。
3つのスキルと成果物を1つのパイプラインとして並べるとこうなる。
laravel-news-pipeline/
├─ skills/
│ ├─ web-content-extraction/ # 本文抽出(Defuddle+SSRFガード)
│ │ └─ scripts/defuddle-url.mjs
│ ├─ laravel-news-catchup/ # 収集→翻訳→検証→索引
│ │ ├─ scripts/fetch-sitemap.mjs # sitemap列挙(依存ゼロ)
│ │ ├─ last-checked.txt # 前回どこまで見たか
│ │ ├─ digests/YYYY-MM-DD.md # 日次キャッチアップの要約
│ │ └─ translations/YYYY-MM/ # 月別の全文訳+README索引
│ └─ laravel-news-monthly-roundup/ # 記事化(月次まとめ生成)
│ └─ assets/check-article.py # 網羅/除外/UTMの決定的チェック
└─ public/laravel-php-YYYY-MM-matome.md # 公開する月次まとめ記事
「収集とアーカイブ」スキルの全文は下の折りたたみに置いた。この手順書があるから、「○月をバックフィルして」と言うだけで毎回同じ品質が出る。
laravel-news-catchup スキル全文(スクラブ済み・そのままは動かない指示書)
記事ではバックフィル側を中心に書いたが、実際のスキルは日次の新着差分キャッチアップも含む。コードはAIに書かせるので、ここにあるのは手順と判断基準だけだ。社内パスや業務文脈はスクラブしてある。
---
name: laravel-news-catchup
description: Laravel News (https://laravel-news.com) の新着記事をキャッチアップする。記事サイトマップで新着URLを列挙し、前回確認(lastmod)からの差分を抽出、必要な記事は本文をDefuddleで取得して日本語で要約する。トリガー例: Laravel Newsを確認/Laravelの新着/今週のLaravel。
when_to_use: Laravel News の新着を定期的に把握したいとき。新しいリリース・パッケージ・チュートリアル・エコシステムの動向を、前回からの差分でまとめて確認したいときに使う。
---
# Laravel News Catch-up
## 目的
Laravel News の新着記事を効率よくキャッチアップする。ブログ一覧ページ(HTML)は
日付が出ず取りこぼしやすいので、記事サイトマップ(sitemap_articles.xml)をURL列挙の
一次情報として使う。各記事の本文・公開日・著者は本文抽出(Defuddle)で取得する。
## 情報源
| 種類 | URL | 用途 |
|---|---|---|
| 記事サイトマップ(一次情報・URL列挙) | https://laravel-news.com/sitemap_articles.xml | 全記事URL+lastmod の取得 |
| 個別記事HTML(精読) | 各記事URL | Defuddleで本文・公開日・著者を取得 |
- サイトマップは <loc>+<lastmod> のみ。title・著者・カテゴリ・要約・公開日は持たない
ので、各記事をDefuddleして補う。
- lastmod は更新時刻で、タイムゾーンは US-Eastern(-04:00/-05:00)。公開日とずれること
があるので、lastmod は新着候補を絞るフィルタにだけ使い、公開日・新着判定は Defuddle の
published で行う。
## 状態管理
- last-checked.txt に、前回取得した新着候補の最大 lastmod(= lastmod の高水位)を入れる。
無ければ初回。
- 既出記事の判定は、別ファイルを持たず既存の digests/*.md に出したURLを正とする。
## 進め方(日次キャッチアップ)
1. 前回の lastmod 高水位を読む:last-checked.txt(無ければ初回)。
2. サイトマップ取得+候補抽出(同梱スクリプト。依存ゼロ・Node標準のみ):
# 前回以降の候補だけ(slackで取りこぼし防止、maxで暴走防止)
node scripts/fetch-sitemap.mjs --since="$(cat last-checked.txt)"
# 初回は全件から新しい順に少数だけ
node scripts/fetch-sitemap.mjs --max=10
出力JSON: { success, sitemapUrl, fetchedAt, since, slackHours, max, truncated,
count, totalUrls, warnings, items:[{url,lastmod,lastmodInstant}] }(lastmod 降順)
- success:false のときは「サイトマップ取得失敗」と明示し、last-checked.txt を進めず止める。
- truncated:true(候補が多すぎ)や長期間の未確認なら、日次の要約でなくバックフィルへ切り替える。
3. 本文取得+新着確定(候補のみ・新しい順):各候補URLを本文抽出で精読し、published で確定:
node ../web-content-extraction/scripts/defuddle-url.mjs "<記事URL>"
- 既存 digests/*.md に既出のURLはスキップ。published(JST) が前回確認より新しいものだけ採用。
- success:false や published 空は「要再取得」として残し次回リトライ(黙って捨てない)。
4. 分類と要約:URLスラッグと title/本文から、リリース / 新パッケージ・ツール /
チュートリアル / エコシステム・その他 に振り分け、本文をもとに日本語1〜2行で要約。
必要なら「自分の業務での使いどころ」を一言添える。
5. 記録と状態更新:要約を digests/YYYY-MM-DD.md に保存し、last-checked.txt を今回の候補の
最大 lastmod で上書きする(新着が0件でも前進させる)。
## フォールバック
同梱スクリプトが動かない場合は raw XML を取得して手で読む:
curl -sL "https://laravel-news.com/sitemap_articles.xml" -o /tmp/laravel-news-sitemap.xml
# 末尾=最新。<lastmod> の新しい順に <url><loc> を数件取り、各URLを Defuddle で精読する
- どの手段でも出典URLと取得日時を必ず残す。取得失敗時は断定しない。
## 過去記事バックフィル(全文翻訳アーカイブ)
特定期間(例: ある月)の全記事を遡って日本語全文訳で残すときも、日次と同じ
sitemap → Defuddle を使う(違いは深さ=全文訳+索引)。
1. 列挙:fetch-sitemap.mjs で対象期間+前後マージンのURLを取る(--since/--max を調整、
または raw sitemap を lastmod で絞る)。
- lastmod は更新時刻で、公開の数日後のことがある。最終的な期間判定は次の
Defuddleの published で行う。
2. 取得+確定:各URLを本文抽出で取得し、published(JST) が対象期間内の記事だけ確定:
node ../web-content-extraction/scripts/defuddle-url.mjs "<記事URL>"
title / author / published / content(Markdown) / fetchedAt を使う。
3. 選別(キュレーション):期間内の記事を、下記基準で 全文訳する記事 と 収録対象外
に振り分ける。対象外は全文訳せず、索引末尾に タイトル|URL|除外理由 の1行だけ
残す(黙って消さない)。
4. 全文翻訳+保存:収録対象の本文を日本語に全文訳(コード・コマンド・識別子・
バージョン・URLは原文維持)し、日本語技術ライティングの規範に従う。冒頭に3行
まとめ+一言メモを付け、translations/YYYY-MM/YYYY-MM-DD-<slug>.md に1記事1
ファイルで保存。
5. 検証:別エージェントで原文と突き合わせ、欠落・コード/版の保全・日本語の自然さ
をチェックし必要なら修正(独立した第三者視点で)。
6. 索引:translations/YYYY-MM/README.md をカテゴリ別に生成し、末尾に「収録対象外
(参考)」を付ける。
7. 規模が大きい場合は「Defuddle取得→翻訳→保存→検証」を記事ごとにパイプライン並列化
する(記事ごとに別ファイルなので競合しない)。
### 収録の選別基準(キュレーション)
全文訳の資産にならない記事は全文訳しない。日次の要約でも同じ基準でトーンを落とす。
収録対象外(全文訳しない/索引は1行):
- 動画コンパニオン記事:本文に技術的実体がなく中身が動画・GitHub頼みのもの。
- 賞味期限の短い単発告知:アンケート/調査の参加募集、IDEバッジ等の小ネタ、締切や
開催で陳腐化するもの。
- 宣伝寄りの機能告知:実務に直結しないベンダー製品のリリース告知。
収録する(全文訳する):
- Laravel コア/フレームワークのリリース(バージョン挙動は必ず残す)。
- 実装・設計の中身があるパッケージ/ツール紹介・チュートリアル。
- エコシステムの節目で実務価値が高いもの(主要カンファレンスの登壇内容など)。
単なる「○○が始まりました」告知は対象外。
判断に迷う記事は収録対象外に倒さず、収録してメモで価値を一言添える(後から消す方が安全)。
## 注意
- 公開日は JST で表記する。
- 要約は日本語。タイトルは原文のままでよい。
- 重要な事実(バージョン番号・非互換変更など)は個別記事の一次情報で裏取りする。
- 1記事も新着がなければ「前回以降の新着なし」と明記して終える。
情報源の罠
過去ぶんをまとめてアーカイブするのが主目的だ。https://laravel-news.com/sitemap_articles.xml に全記事のURLが日付つきで載っているので、新着の差分も過去の遡りも、ここから対象を拾う。
ただし sitemap の <lastmod> は更新日時で、公開日とずれる。実際、先月公開の記事が今月の lastmod で並んでいたことがあった。なので sitemap はURLの列挙にだけ使い、どの月かは記事本文の公開日(published を JST に直したもの)で確定する。
いつ走らせても、前回の続きから
この sitemap と「前回どこまで見たか」(last-checked.txt)の組み合わせが、最初の悩みに効く。前回確認した位置を覚えているので、いつ実行しても前回以降の新着だけが対象になる。毎日でも、数週間ぶりでも、空いた分はまとめて差分で埋まる。月の途中で一度アーカイブを作り、月末にまた走らせれば、増えたぶんだけ足される。「どこまで読んだか」を自分で抱えなくてよくなった。
本文抽出は専用ツールに任せる
本文抽出には、スターターキットに入っていた web-content-extraction スキルをそのまま使った1。生HTMLをそのままLLMに渡すより精度が出る。自分は呼び出しているだけで、抽出も SSRF2 ガードも中身は書いていないし、手を入れてもいない。
なお、月の確定に使う公開日(published)も、Defuddle がページのメタデータ3(OGP の article:published_time や schema.org の datePublished など)から読むものだ。ニュースやブログはたいてい出しているが、どのソースにも必ずあるとは限らない。更新日しか持たなかったり、日付が本文テキストにしか無いサイトでは取れない。その場合は公開日で月を確定できないので、取れなかった記事はその回では確定させず次に回す(「要再取得」にして黙って捨てない)。
何を載せ、何を落とすか
全部を機械的に訳すと、動画の紹介だけの記事や賞味期限切れの告知まで溜まる。なので動画コンパニオンと短命な告知(アンケート募集、IDEバッジ等)は落として、リリースや中身のあるパッケージ紹介だけ訳した。落とした記事も、索引に「タイトル|URL|除外理由」を1行だけ残す。
検証は別のエージェントにやらせる
1か月ぶんの翻訳は数十本になる(多い月で40本超)。そこで、翻訳した本人ではなく別のエージェントに検証させる。自己採点が甘くなるからだ。
検証側が見るのは、段落やコード例の欠落、クラス名やバージョンの保全、日本語の自然さだ。ただし「原文に根拠がある箇所だけ直す」という縛りを検証プロンプトに入れてある。正しい訳を別エージェントが良かれと思って改悪するのを防ぐためだ。
たとえばあるパッケージ紹介では、見出しが Installation Usage のまま英語で残っていた。検証エージェントが、同じ月の他の訳に合わせて「インストール」「使い方」へ直した。翻訳した本人はできたつもりでいた箇所だ。別の記事では、本文の手順説明が訳の途中で数行に要約されて中身が抜けていた。これも検証側が原文と突き合わせ、省かれた部分を訳し直した。見た目には完成して見えるぶん、原文と照らさないと気づけない欠落だ。
最後の機械チェック
翻訳の検証(前節)とは別に、出来上がった月次まとめ記事のレビューもAIにやらせる(技術精度、日本語、体裁を別々のエージェントで)。ただし最後の確認だけはAIに任せない。まとめ記事を、数十行のPythonで機械的に検査するだけだ。見るのはこの3つ。
- 収録した記事を全部1回はリンクしているか(載せ忘れ)
- 除外した記事を載せていないか(出どころ不明のリンク)
- URLに計測パラメータ(UTM)が混ざっていないか
AIの判断がブレても、ここで弾ける。
ただし、この機械チェックが見るのは構造だけ。訳の正しさ自体は別エージェントの検証と、まとめを書くとき自分が通す目に委ねている。翻訳AIと検証AIが同系統である以上、同じ誤読を双方が見逃す余地は残る。そこは正直、完全には潰せていない。
ハマりどころ
実際に半年ぶんを流すと、きれいには終わらなかった。
- 数か月ぶんは1セッションで終わらない。途中で止まらないよう、Claude Code の
/goalに「1月分まで終わるまで」のような完了条件を置いた。条件を満たすまで止まれないので、放っておいても最後まで回り続ける。失敗の再実行(次項)と組み合わせると、寝ている間に進む。 - 長時間実行でAPIの接続が切れる。数十記事を一度に回すと、途中で翻訳や検証のエージェントが落ちる。落ちたぶんだけを拾って再翻訳と再検証をする「埋め戻し」を別に用意した。最初から落ちる前提で、欠落検出と再実行をセットにしておくべきだった。
- 日付の境界でブレる。米国東部の夜に公開された記事はJSTだと翌日にずれ、月末・月初がどちらの月か揺れる。さらに
lastmodが今年でも前年公開の記事が紛れ込むことがある(実際、2025年の記事が1本混ざっていた)。公開日(JST)の「年月」で機械的に振り分け、際どい数本だけ手で寄せた。 - sitemap が一時的に404。サイト側の都合で sitemap が引けない日があった。前日に取得済みのものへフォールバックして止めずに済ませた。
アーカイブと公開記事
2026年1〜6月で、月別アーカイブはこうなった。
| 月 | 収録記事 |
|---|---|
| 2026-01 | 45 |
| 2026-02 | 38 |
| 2026-03 | 35 |
| 2026-04 | 42 |
| 2026-05 | 36 |
| 2026-06 | 28 |
| 計 | 224 |
アーカイブは月ごとに、全文訳の個別記事(各 .md がフロントマター+3行まとめ+本文の全文訳)とカテゴリ別の README 索引で構成される。そこから書いた月次まとめ6本がこれだ。
- 【2026年1月】Laravel/PHP 今月のまとめ
- 【2026年2月】Laravel/PHP 今月のまとめ
- 【2026年3月】Laravel/PHP 今月のまとめ
- 【2026年4月】Laravel/PHP 今月のまとめ
- 【2026年5月】Laravel/PHP 今月のまとめ
- 【2026年6月】Laravel/PHP 今月のまとめ
Qiita のまとめは人に読んでもらう用だが、半年後に「5月は何があったか」を月1本で引ける索引になっているのが、書いた自分にいちばん効いている。
他のソースに流用するなら
Laravel News に限らず、英語の技術ソースを追う場面に同じ骨格が使える。
-
日付は
lastmod(更新日)でなく本文の公開日で月を確定する。タイムゾーンは1つに統一する(自分は JST)。ただし公開日メタ(OGP/schema.org 等)はソース次第で無いこともあるので、無ければ本文中の日付や手動で補う。 - 本文抽出は専用ツール(Defuddle など)に任せる。外部URLを叩くなら SSRF 対策を入れる。
- 翻訳と検証は別のエージェントに分ける。自己採点はしない。
- 何を収録し何を落とすかの基準を、コードでなく文章(スキル)で明文化する。落とした分も理由を1行残す。
- 最後の確認は決まったスクリプトで機械的にやる(網羅と除外、リンクのチェック)。
- 配布の線引きを最初に決める。全文訳は私的利用にとどめ、公開は出典リンク付きの要約だけにする(原文の全文転載はしない)。
-
前述の Claude Code Starter Kit(Cloud Native Inc./MIT)のスキル。Defuddle でHTMLのノイズ(ナビ・フッタ等)を除いて本文を Markdown 化し、外部URL用の SSRF 対策(プライベートIP・DNS リバインディングの遮断)や Defuddle の upstream 追従まで最初から内蔵している。 ↩
-
SSRF(Server-Side Request Forgery)=外部から渡したURLを使って、サーバーに社内ネットワークやクラウドのメタデータ等へアクセスさせる攻撃。対策では併せて DNS リバインディング(名前解決時と接続時でIPをすり替える手口)も塞ぐ。 ↩
-
OGP・schema.org=ページに埋め込む構造化メタデータの規格。SNS共有や検索エンジン向けに、公開日・著者・タイトルなどを機械可読な形で宣言する。 ↩
