BigQuery×Geminiでスクレイピングデータの週次レポートを自動生成する
はじめに
これは「GitHub Trendingデータ基盤構築編」シリーズの続編です。
前回の記事では、GitHub TrendingをスクレイピングしてDataflowで整形し、BigQueryに構造化データとして蓄積するパイプラインを構築しました。
今回はその続きとして、BigQueryに蓄えたデータをGeminiに渡して週次技術トレンドレポートを自動生成するところまでを紹介します。BigQueryに蓄えたデータを生成AIでうまく活用できないかという試みでした。
前回記事:https://zenn.dev/acntechjp/articles/970c2d3063ab80
やりたいこと
シンプルに以下の流れを実現します。
- BigQueryから直近7日分の急上昇リポジトリを抽出
- 結果をJSONにしてGeminiに渡す
- 人が読める週次レポート(Markdown)を生成
アーキテクチャは次のような構成です。
- Dataflow: GitHub生データをクレンジングしてBigQueryにロード
- BigQuery: 期間・言語・スター数などで集計・フィルタ
- Gemini: JSON+プロンプトから週次レポートを生成
つまり「BigQueryのSELECT結果を、そのままLLMに食べさせる」という形になります。
BigQuery: データの切り出し
まずLLMに渡すデータをSQLで準備します。設計方針は以下の通りです。
- 対象期間: 直近7日間
- 優先順位:
today_stars(本日増加分)→stars(総スター数)
SELECT
article_id,
source,
title,
url,
author,
description,
stars,
today_stars,
language,
collected_at,
tags
FROM tech_trends.raw_articles_dedup
WHERE DATE(collected_at) BETWEEN DATE_SUB(CURRENT_DATE(), INTERVAL 7 DAY)
AND CURRENT_DATE()
ORDER BY today_stars DESC NULLS LAST,
stars DESC NULLS LAST
LIMIT 50;
ポイントは、ランキングや期間の切り方をSQL側で完結させることです。LLMに「このテーブルからいい感じに選んで」と丸投げすることもできますが、ロジックがブラックボックスになり結果がぶれやすいため、集計とフィルタはBigQueryに寄せています。
PythonでBigQueryとGeminiをつなぐ
データ取得からレポート生成までを1本のスクリプトで実装しました。
BigQueryからデータ取得
from google.cloud import bigquery
import json
bq = bigquery.Client()
query = """
SELECT ※ここに上記のSQLを入れる
;
"""
rows = list(bq.query(query))
data = [dict(row) for row in rows]
# TIMESTAMP型をJSON化するためdefault=strを指定
json_data = json.dumps(
data,
ensure_ascii=False,
indent=2,
default=str,
)
Geminiにプロンプトを投げる
プロンプトでは「どんな構成のレポートを出してほしいか」を明確に指定しました。
※実際はもう少し長いプロンプトで指示しています。
from google import genai
from google.genai.types import HttpOptions
client = genai.Client(
vertexai=True,
project="YOUR_GCP_PROJECT_ID",
location="asia-northeast1",
http_options=HttpOptions(api_version="v1"),
)
prompt = f"""
あなたは技術トレンドを分析するアナリストです。
以下は過去7日間のGitHub Trendingデータ(Dataflowでクレンジング済み)です。
【出力項目】
1. 今週のサマリ(マネージャー向け、3〜5行)
2. 技術トレンド概要(言語別・カテゴリ別)
3. 急上昇リポジトリ(today_stars重視)
4. 注目リポジトリ3つ+理由
5. 今後の学習・ウォッチ対象
【データ項目】stars, today_stars, language, tags, description
【出力形式】日本語、箇条書きと短い段落、エンジニア〜マネージャーレベル
--- JSONデータ ---
{json_data}
"""
response = client.models.generate_content(
model=model="gemini-2.5-pro",
contents=prompt,
)
print(response.text)
LLMには「集計」ではなく「解釈と説明」を任せるイメージです。
生成されたレポートの例
実際に出力されたレポートテキストをMDファイルでPDF化したもの(抜粋)です。
BigQueryで計算した数値とdescription/tagsを組み合わせて、LLMが適切にまとめています。



役割分担の整理
今回の構成を通して、各コンポーネントの役割分担が明確になりました。
Dataflow
- GitHub生データのクレンジング
- 重複排除、フィールド正規化
- LLMが読みやすいテーブルをBigQueryに用意
BigQuery
- 期間・指標・言語などでフィルタ・集計
- どの行をLLMに見せるかを決定
- 数値の計算・集計はすべてこちらで完結
Gemini(LLM)
- BigQueryの結果(JSON)+descriptionを入力
- カテゴリ分類・要約・サマリの生成
- 人間が読むレポートに仕上げる
LLMに生ログをそのまま投げるのではなく、事前に構造化・正規化されたテーブルに落としておくことが重要です。
まとめ
DataflowでBigQueryに蓄えたGitHub TrendingデータをGeminiに渡して週次レポートを自動生成する方法を紹介しました。
ポイントは以下の3点です。
- 集計とフィルタはBigQueryで完結させる
- LLMは「定量結果の解釈と文章化」に特化させる
- データを事前に構造化しておくことで結果が安定する
応用先としては、各種トレンド分析、業務レポートの自動生成など様々あるように思います。
「Dataflow / BigQueryでデータを整え、最後の説明だけをLLMに任せる」というパターンは汎用性が高く、さまざまな場面で転用できそうです。
GCPでデータパイプラインと生成AIを組み合わせたい方の参考になれば幸いです。
おまけ:Claude opus4.5にこの件でパワポを作らせたらさらに洗練されていました。手直しも数えるほどしか発生せず。すごい。

Discussion