LLMで反復作業を定型化し,スクリプトにする
LLMの登場によって,その場ごとになんとなくこなしていた反復作業の定型化・自動化が簡単になったと思う.
具体的には,(1)作業の反復に気付いたら抽象化して曖昧な言葉でLLMに伝えると(2)それが言葉の上で定型化される.
(3)2を手直ししてできた作業フローの一部をスクリプトに実装すると,部分的な自動化も達成される.
これにより,生活や仕事の作業にプログラムを組み込みやすくなった.
具体例
Gmail上でラベル分けされたScholarアラートから文献リストを生成するGoogle Apps Script(試作)
Google Scholarのアラート通知の確認の一部を自動化したときの記録
「リンク先を確認して翻訳ソフトで概要を確認して仕分ける」という作業の反復が,「翻訳付きの一覧リスト生成」という自動スクリプトを作ることにより省力化された
プロンプトtomiokario.icon
gmailにGoogle Scholarのアラートを飛ばしていて,それらを自動分類でラベル毎に分けています. 各ラベルの割り振られたメールについて,タイトルと概要の翻訳,ペイウォールの有無あたりを何かしら(メールでもスラックでもnotionでもGoogle Officeでもなんでも良い)で一覧できるような仕組みを作りたいです.アプローチを調べてください. Google Scholarのメールはhtml方式で複数の論文が届くこともあり,それらが他のメールと重複することもあります.htmlからリンクを抽出して,そこから情報を取ってきて,重複の有無などを確認する仕組みを動かして,翻訳などの後処理を考える必要があります.
GPT-5
いいですね。その要件なら「Gmail →(本文HTMLを分解)→ 論文メタデータ解決(DOI/ID探し)→ OA/ペイウォール判定 → 重複排除 → 翻訳 → 一覧出力」のパイプラインを作れば堅実に回せます。実装負荷と運用の楽さで、現実的なアプローチを4系統にまとめました。どれも「Google Scholarのメール本文からリンクを抽出 → DOIやarXiv IDを解決 → 公開可否(OA)判定 → 日本語要約/翻訳 → 一覧化」を行います。
推奨アーキテクチャ候補
A. Google Workspaceネイティブ(Apps Script + Google Sheets)
概要:Gmailのラベルごとにメールを取得 → HTML本文からタイトル・リンク群を抽出 → Crossref/OpenAlex/Semantic ScholarでDOI等を引き → UnpaywallでOA/ペイウォール判定 → 翻訳(Cloud Translation)→ 1枚のスプレッドシートに集約。
長所:Googleアカウント内で完結/運用が軽い/表形式の一覧がすぐ共有可。
技術要素
メール取得:Gmail API または Apps Script の GmailApp。()
HTML解析:本文 getBody()/getRawContent() を正規表現 or HTMLパーサで抽出(Apps Script事例あり)。()
DOI/ID解決:Crossref REST(/works 検索・select最適化)、OpenAlex(/works 検索・外部ID指定)、Semantic Scholar。()
OA判定:Unpaywall(DOI→oa_status= gold/green/hybrid/bronze/closed)。()
翻訳:Cloud Translation API v3。()
出力:Google Sheets(Apps ScriptのSpreadsheetApp)。
重複排除:
1. 正規化したDOI(小文字・doi.org/除去)、2) arXiv ID、3) 正規化URL(トラッキング除去)、4) タイトルのファジー一致(閾値0.9など)。
ペイウォール判定ロジック:
DOIあり→ Unpaywallのis_oaとoa_status/best_oa_locationを採用。()
DOIなし&arXiv等→ arXiv直リンクは「OA=Yes」。
最終チェック→ PDF直リンクにHEADでContent-Type: application/pdf確認(可用なら)。
向いている場合:まずは1日1回自動で「ラベル別・新着だけ追記」する一覧が欲しい。
B. Notionデータベース連携(Gmail→ワーカー→Notion)
概要:小さなPython/Cloud FunctionsがGmailを読み、レコードをNotion DBにUpsert。ビュー/フィルタで運用。
長所:フィールド設計の自由度/コメント・プロパティ運用が楽。
技術要素:Notion API(DB作成・ページ作成/更新)。()
向いている場合:既存の知識ベースがNotion中心、タスク化やタグ運用も一元化したい。
C. SlackダイジェストBot(毎朝まとめを投下)
概要:前日分の新着をまとめて「チャンネル1投稿+スレッドでラベル別」などで配信。
技術要素:Slack Web API chat.postMessage/Incoming Webhook。()
向いている場合:閲覧はSlackが主。一覧はSheet/Notionに保存し、Slackは通知+要約だけ。
D. ローカル/サーバーサイド スクリプト(Gmail API + CSV/Markdown出力)
概要:手元 or 小規模サーバーでCron実行し、Obsidian/Notion取り込みやCSV出力に合わせる。
長所:自由度が最大。研究用途の細かい前処理(正規化・辞書置換など)を詰めやすい。
注意:鍵管理・デプロイ・エラー監視は自前。
処理フロー(どの案でも共通)
1. 取得対象
Gmailの対象ラベルごとに未処理メールを検索(label:scholar-alerts after:YYYY/MM/DD など)。Gmail APIのページング/フィルタ挙動は公式ガイド参照。()
2. HTML解析
ScholarアラートはHTML本文内に複数エントリ(gse_alrt_title 等のアンカー)があり、1通=複数論文ケースを想定。リンク(scholar_urlの中継URL)を最終URLに解決し、arxiv.org, doi.org, 各出版社リンクを抽出。(Apps ScriptやJSでのHTML抽出の実例・解説あり)()
3. メタデータ解決(堅牢性のため多段フォールバック)
優先順:(a) DOI 直読み(URLにdoi.orgを含む)→ (b) Crossref 検索(タイトル+著者+年)→ (c) OpenAlex 検索/ID解決(/works?search=... または /works/https://doi.org/...)→ (d) Semantic Scholar(タイトル/URL/DOIから)。()
4. OA/ペイウォール判定
Unpaywallでis_oa・oa_status(gold/green/hybrid/bronze/closed)を取得。表示には「OA=Yes/No」「種別」「best_oa_locationのURL」を格納。()
OpenAlexにもAPC情報など付随データあり(任意)。()
5. 重複排除
キー優先:doi_norm → arxiv_id → url_norm → title_fuzzy。
既登録DBとUpsert(キーが一致なら更新/スキップ)。
6. 翻訳(タイトル/アブストラクト・スニペット)
Google Cloud Translation v3(複数文の一括翻訳、用語集も可能)。()
研究分野の用語誤訳を避けたい場合は用語集(Glossary)を設定。()
7. 出力
Sheets:列例(日時, ラベル, 著者, タイトル, タイトルJP, 出版年, 収録先, DOI, arXiv, URL, OA種別, OAリンク, スニペットJP, 取得元メールID, 既読/未読, 重複フラグ)。
Notion:同等プロパティでDB化(セレクト=ラベル、チェックボックス=OA/重複など)。()
Slack:日次まとめ(件数・OA内訳)+各論文をBlock Kitで整形して投稿。()
実装のポイント(ミニ仕様)
メール → 論文アイテム
1通のメールからN件の候補を展開し、各候補に「元メールのラベル」「メール日時」「差出人」「Message-ID」をメタとして付与。Gmail APIのメッセージスキーマで取得可。()
URL正規化
scholar_url?url=... のようなリダイレクトつきURLを展開し、utm_*等のトラッキングパラメータを除去してキーとする。
APIの使い分け
DOIがあればUnpaywall一発、DOI不明時はCrossref/OpenAlexでまずDOI解決→Unpaywall。()
OAの解釈
gold/green/hybrid/bronze/closed の定義はUnpaywall準拠でラベル化。()
翻訳コスト
Cloud Translation v3は従量課金。研究内向けならタイトル/要旨だけを翻訳し、本文は必要時にオンデマンド翻訳に。()
どれを選ぶべきか(短評)
最短到達:A(Apps Script+Sheets)
Google環境に閉じ、デプロイも簡単。週次/日次トリガーだけで回る。
管理・検索性重視:B(Notion)
DBビューやフィルタ、コメント運用が強い。既にNotion中心なら最適。
通知重視:C(Slack)
実作業はSheet/Notionに集約、Slackは読む入口に。
細かい前処理・研究向け:D(自前スクリプト)
前処理・重複判定のカスタムや将来のRAG連携まで見据えるなら。
データ項目(例:必須/推奨)
必須:元ラベル/メール日時/タイトルEN/タイトルJP/URL(正規化)/DOI/arXiv ID/OA可否/OA種別/OAリンク
推奨:著者/年/ジャーナル/要旨JP(短め)/重複フラグ/出所(Google Scholar alert / 他)/Message-ID
注意(TOSと安定運用)
Google Scholarのスクレイピングは避け、メール本文内のリンクを出発点にする(本文解析は自分の受信物に対する処理)。
API制限:Crossref/OpenAlex/Semantic Scholar/Unpaywall にはレート制限あり。大量処理はバッチ化やキャッシュを。()
Unpaywallの無料スナップショットは更新頻度が低め。常時最新を望むならAPIを使う(またはData Feed契約)。()
翻訳コストは要予算管理(Advanced v3推奨、Glossary活用)。()
プロンプトtomiokario.icon
最初に述べた仕組みをAで実装する手順書を作成してください
GPT-5
了解です。A案(Apps Script+Google Sheets)で**「Gmailのラベル別にScholarアラートを収集 → HTMLから各論文を分解 → DOI/ID解決 → UnpaywallでOA判定 → タイトル/スニペット翻訳 → シートに追記(重複はUpsert)」*を作るための手順書をまとめます。まずは最小構成で動く→あとから精度向上やGlossary翻訳などを足せる構成です。
全体像
入力:Gmail(ラベル=例:scholar/ozcan など)
処理:HTML解析 → Scholarリダイレクト展開 → DOI/ID解決(DOI/arXiv/Crossref→OpenAlex) → UnpaywallでOA判定 → 翻訳(タイトル/スニペット)
出力:Googleスプレッドシート(1行=1論文)。既存キー(DOI/arXiv/正規化URL)でUpsert運用
運用:Apps Scriptの時間主導トリガーで日次/時間毎に自動実行
0. 事前準備
1. スプレッドシートを1つ作成
シート名:alerts(任意)
ヘッダー行(A1〜):captured_at,label,email_msg_id,title_en,title_ja,authors,year,venue,doi,arxiv_id,url_norm,oa,is_oa,oa_status,oa_url,snippet_en,snippet_ja,source,dup_key
このスプレッドシートのURLから Spreadsheet ID を控える(.../spreadsheets/d/<ここ>/edit)
2. Unpaywall用メールを準備
APIは無料ですが、[* ?email=your@email] を必ず付与
そのメールアドレスを後でScript Propertiesに保存
3. Gmailのラベルを決める
例:scholar/* 階層を用意(テーマや人物別に)
まずは1つのラベルから着手 → 後で配列に複数追加
1. Apps Script プロジェクト作成
1. Googleドライブ → 「新規」→「その他」→「Google Apps Script」
2. プロジェクト名を付与(例:Scholar Alert Harvester)
3. スクリプトプロパティを設定(ファイル → プロジェクトのプロパティ → スクリプトのプロパティ)
SPREADSHEET_ID:上で控えたID
SHEET_NAME:alerts
UNPAYWALL_EMAIL:あなたのメール(API用)
LABELS_JSON:["scholar/ozcan"] のようにJSON配列文字列
(任意)DAYS_LOOKBACK:7 など[
2. 最小実装コード(貼り付け用)
下のコードをCode.gsに貼り付け → 保存 → 実行する関数は runHarvest。
初回実行時は**Gmail/スプレッドシート/外部接続(UrlFetch)の権限を許可してください。
(長かったためこの記録ではコードは省略しています.読みたい場合は最小実装コード| GitHub Gistを参照してください)tomiokario.icon
補足 LanguageApp.translate() は手軽ですが品質の制御が弱いです。必要に応じて Cloud Translation v3 に置換してください(後述)。
既存行の更新(Upsertの“Update”)が必要な場合は、dup_key→行番号のマップを作り、sheet.getRange(row, col).setValues(...) で差し替える関数を追加します(最初は追記のみ]で十分回ります)。
3. 時間主導トリガー(自動実行)
Apps Script 画面右側の「トリガー」→「トリガーを追加」
実行する関数:runHarvest
イベントのソース:時間主導型
時間ベースのトリガー:日付ベース/午前9時 など(東京時間)
4. Cloud Translation v3(オプション:精度・用語集対応)
より良い翻訳(Glossary、ドメイン適合など)を使う場合:
1. GCPプロジェクトを用意(課金有効化)
2. Translation API v3 を有効化、APIキーまたはOAuthを発行
3. Apps Script からは UrlFetchApp.fetch で https://translation.googleapis.com/v3/projects/<PROJECT_ID>/locations/asia-northeast1:translateText を呼ぶ
4. 用語集(Glossary)を使う場合は Cloud Storage にTSVを配置 → Glossary作成実装は translateJa() を置換するだけです(レート制御と課金注意)。最初は LanguageApp で十分です。
5. 精度改善のための小技(後からでOK)
タイトル揺れ対策:Crossref→OpenAlexの順で二段検索(既に実装)。閾値を付けたい場合はタイトルの正規化(小文字化、括弧除去、記号除去)でスコアリング。
URL正規化:utm_* 以外にも ref, fbclid, gclid などの追跡パラメータを削除。
arXiv vN:abs/2510.03938v2 のvN を落として保存(既に正規表現で吸収)。
重複判定の第4キー:タイトルのファジー一致(Levenshtein > 0.9 など)を後日追加。
Unpaywallフォールバック:HTTP 404/429時の指数バックオフ&キャッシュ(PropertiesService やシート別タブにキャッシュ)
取得範囲:DAYS_LOOKBACK を適宜調整。大量処理時はページング&Utilities.sleep()でレート回避。
6. 動作確認手順(最初の1本)
1. LABELS_JSON に 1つだけ ラベル(例:["scholar/ozcan"])を入れて保存
2. Gmailでそのラベルの最近のアラートが1〜3通ある状態に
3. runHarvest を手動実行 → スプレッドシートに行が追加されることを確認
4. doi や arxiv_id が入った行では oa/oa_status/oa_url が埋まることを確認
5. 翌日以降はトリガーで自動追記(同じ論文は dup_key で抑止)
7. 運用上の注意
Scholar本文の解析は自分の受信メールに対する処理であり、外部サイトのスクレイピングは行わない設計。
APIレート(Crossref / OpenAlex / Unpaywall)は短時間に大量投げない。連続処理時は Utilities.sleep(200) などで間引き。
翻訳コスト:Cloud Translation v3は従量課金。まずは LanguageApp → 品質課題が出たら移行。
権限:Apps ScriptのスコープはGmail・スプレッドシート・外部接続(UrlFetch)。初回許可が必要。