國會會議記錄搜尋技能
透過 NDL(國立國會圖書館)的國會會議記錄搜尋系統 API 調查自國會成立(1947 年)以來的日本國會議事錄。無需認證。使用 bash scripts/<script>.sh wrapper 來呼叫。
帝國議會議事錄(〜1947 年)屬於不同 API,因此不在本技能範圍內。
基本規則
- Base URL:
https://kokkai.ndl.go.jp/api/ - 回應格式:
recordPacking=json(wrapper script 會強制設定) - 認證: 不需要
- 呼叫方式: 使用
bash scripts/<script>.sh。直接使用WebFetch/Invoke-RestMethod僅限於 wrapper 未覆蓋的邊緣案例(請參閱下方「需要 raw curl 的情況」) - 速率限制: 官方明確規定「進行機械性存取時,禁止多重請求,應間隔數秒」。禁止並行處理,連續呼叫應間隔約 2-3 秒。
- 查詢字串總長度上限為 2,000 位元組(日文字元經 URL 編碼後,每個字元約佔 9 位元組)。
端點選擇
根據使用者的需求選擇適當的 wrapper script。資訊量與消耗的 token 依 list-meetings.sh < search-by-*.sh < fetch-meeting.sh 的順序遞增,因此應從較輕量的端點開始逐步篩選。
「顯示某議員的發言」
→ bash scripts/search-by-speaker.sh 議員名稱 [from] [until] [limit] --sort <keys>
※ --sort 為必填。代表值為 date-desc(最新優先)
「搜尋關於某主題的發言」
→ bash scripts/search-by-keyword.sh 關鍵字 [from] [until] [limit] --sort <keys>
※ any 搜尋(AND 邏輯)。多個關鍵字以半形空格分隔。--sort 為必填
「抽取參考人質詢(包含證人喚問、陳述人)」
→ bash scripts/search-by-role.sh 角色名稱 [from] [until] [limit] --sort <keys>
※ role 可以是 證人 / 參考人 / 陳述人。--sort 為必填
「顯示某委員會的會議列表」
→ bash scripts/list-meetings.sh 委員會名稱 [from] [until] [limit] --sort <keys>
※ 輕量級端點。僅回傳會議中繼資料(不含發言本文)。`--sort` 為必填(僅接受 `date-asc` / `date-desc`)
「顯示特定會議的所有發言」「某委員會 YYYY-MM-DD 的完整議事錄」
→ 步驟 1: 使用 bash scripts/list-meetings.sh 找出目標會議的 issueID
→ 步驟 2: 使用 bash scripts/fetch-meeting.sh <issueID>
※ 一個請求會回傳完整會議內容,因此資料量較大。務必先進行篩選再呼叫。
詳細資訊請參閱 api-reference.md、parameters.md、response-format.md 與 recipes.md。
各端點的使用方法
1. search-by-speaker.sh — 依議員名稱搜尋發言(最常用)
僅回傳符合搜尋條件的發言。Token 效率最佳。--sort 為必填,這迫使使用者明確瞭解 API 的排序規則(針對 #41 的對策)。
# 依議員名稱抽取發言(部分比對 OR),日期降序
bash scripts/search-by-speaker.sh 岸田文雄 2024-01-01 2024-12-31 50 --sort date-desc
所有參數規格(包含可用的 sort key 詳細資訊)請參閱 bash scripts/search-by-speaker.sh -h。
回應為 speechRecord[] 陣列。每個元素會扁平化包含會議中繼資料(如 issueID、session、nameOfHouse、nameOfMeeting、date 等)。
2. search-by-keyword.sh — 關鍵字搜尋(any 搜尋,AND 邏輯)
針對發言本文進行全文搜尋。多個關鍵字以半形空格分隔,進行 AND 組合。--sort 為必填。
# AND 搜尋: 包含「マイナンバー」且包含「個人情報」的發言,日期降序
bash scripts/search-by-keyword.sh 'マイナンバー 個人情報' 2024-01-01 2024-12-31 50 --sort date-desc
所有參數規格請參閱 bash scripts/search-by-keyword.sh -h。回應結構與 search-by-speaker.sh 相同。
3. search-by-role.sh — 依角色搜尋發言(例如參考人質詢)
根據 speakerRole 來篩選發言者的角色。用於抽取證人喚問、參考人質詢或陳述人的發言。--sort 為必填。
# 僅限參考人質詢,日期降序
bash scripts/search-by-role.sh 參考人 2024-01-01 2024-12-31 50 --sort date-desc
role 只能是 證人 / 參考人 / 陳述人 其中之一。指定其他值時,API 會回傳 HTTP 400 錯誤。
所有參數規格請參閱 bash scripts/search-by-role.sh -h。
4. list-meetings.sh — 會議列表(輕量級索引)
僅回傳會議中繼資料。不包含發言本文,因此適合用於產生列表或進行初步篩選。用於找出 issueID。--sort 為必填(僅接受 date-asc / date-desc)。
# 特定日期的預算委員會列表,日期升序
bash scripts/list-meetings.sh 預算委員會 2024-03-01 2024-03-31 50 --sort date-asc
所有參數規格請參閱 bash scripts/list-meetings.sh -h。
回應為 meetingRecord[] 陣列。每個元素下的 speechRecord[] 包含最低限度的發言中繼資料(speechID、speechOrder、speaker、speechURL)。取得本文需要呼叫 search-by-* 或 fetch-meeting.sh。
5. fetch-meeting.sh — 完整會議記錄(最終手段)
回傳完整會議記錄。一個請求就會回傳所有發言,因此資料量較大。請先使用 list-meetings.sh 找出 issueID 後再呼叫。
# 依 issueID 取得完整會議記錄
bash scripts/fetch-meeting.sh 121405254X00220241004
參數規格請參閱 bash scripts/fetch-meeting.sh -h。maximumRecords=1 為固定值(因為 issueID 是唯一的)。--sort 在此端點不適用(因為是取得單一會議;必要時可使用 jq 對輸出進行後處理)。
fetch-meeting.sh 的 speechRecord[] 包含所有欄位(speech、speakerYomi、speakerGroup、speakerPosition、speakerRole、startPage、createTime/updateTime)。
Token 節約指引
bash scripts/fetch-meeting.sh 一個會議的資料量可能達到數百 KB 到 MB 等級。應遵守以下事項:
- 優先使用
search-by-*.sh: 以發言為單位時,可以只取得需要的部分。bash scripts/fetch-meeting.sh僅在使用者明確要求「完整會議記錄」時使用。 - 明確指定
maximumRecords: 預設值 30 足夠時可省略。需要取得大量資料時,可提高上限(search-by-*/list-meetings: 100、fetch-meeting: 10)以減少總請求數。 - 採用兩階段搜尋: 先使用
list-meetings.sh或search-by-*.sh篩選目標並取得issueID,再視需要呼叫fetch-meeting.sh取得完整記錄。不要一開始就直接呼叫fetch-meeting.sh。 - 命中 0 筆時的重新嘗試,請嘗試不同表記: 議員名稱可依序嘗試
福島 みずほ/福島瑞穗/ 平假名。黨派名稱必須使用正式名稱(自民黨❌ /自由民主黨✅)。
結果篩選的陷阱
取得回應後,請注意以下事項:
speechOrder為0的行是議事錄資訊標頭: 這些是議事日程、審議案件等結構化資訊,並非實際發言。speaker固定為會議記錄資訊。統計發言時,應排除speechOrder為0的行。imageKind的值: 預設情況下,除了會議記錄之外,目次/索引/附錄/追錄也可能混入。抽取發言時,應將imageKind的值過濾為僅會議記錄的行(請求參數contentsAndIndex/supplementAndAppendix預設均為false,因此通常可省略。只有在需要明確混入這些項目時才指定true)。closing會在值為false時回傳null: 在未設定閉會中旗標的一般會議中,其值為null。判斷是否為閉會中審查時,應檢查closing的值是否為true(應使用與true的比較,而非與false的比較)。nameOfHouse的無效值會被靜默忽略: API 會回傳 HTTP 200 但結果未套用篩選。請透過檢查numberOfRecords的合理性來確認篩選意圖是否被正確反映。- 發言本文的換行為 CRLF (
\r\n): 並非僅有 LF。進行文字處理時,可能需要進行正規化。 search-by-*.sh的回應結構是扁平化的: 不像fetch-meeting.sh那樣有meetingRecord包裝。若要編寫通用解析器,需要進行分支處理。- API 的排序順序固定為「會議召開日期的降序」: 官方規格保證排序為降序,API 端沒有排序參數(search-by-speaker / search-by-keyword / list-meetings / fetch-meeting 皆同)。本技能的 wrapper script 的
--sort並非 API 參數,而是透過jq進行的客戶端排序後處理(search-by-*.sh/list-meetings.sh為必填)。雖然方便,但若使用maximumRecords進行部分擷取,則只會回傳最新的 N 筆。- 判斷最新發言: 可透過部分擷取的開頭確認(
maximumRecords=1即足夠)。 - 判斷最舊發言: 不要根據部分擷取的結果來判斷最舊發言。需要取得
numberOfRecords的所有頁面,或者使用from/until將期間縮小到年等單位,直到命中筆數 ≤maximumRecords後再進行判斷。 - 同一天內的次要排序為
speechOrder升序(實測結果,非官方規格): 如果不縮小期間,直接使用startRecord=<numberOfRecords>&maximumRecords=1存取最後一頁,由於 API 固定為降序,會取得期間內最舊日期的當日最後一筆發言(speechOrder最大),從而錯過真正的第一筆發言。請使用from/until將期間縮小到numberOfRecords ≤ 100並取得所有筆資料,然後使用 wrapper 的--sort date-asc,speech-order-asc在一個請求內確定。(詳細請參閱 recipes/oldest-speech-by-speaker.md)。
- 判斷最新發言: 可透過部分擷取的開頭確認(
- 同時使用
any與speaker會產生交集(筆數大幅減少): 若為了搜尋議員 A 的發言而同時指定any=A&speaker=A,搜尋結果將僅限於同時滿足兩個條件的發言(即 A 本人在發言中提到自己名字的情況),筆數會比單獨使用其中一個條件大幅減少(實測: 單獨使用speaker=石原慎太郎為 2,098 筆 / 兩者併用為 647 筆)。要取得議員 A 的所有發言,請單獨使用speaker;要搜尋提及 A 的發言,請單獨使用any。不同意圖的使用方式請參閱 parameters.md 的相關章節 與 recipes/speaker-vs-any-disambiguation.md。 (19004)startRecord 超出範圍錯誤中的「搜尋筆數」是指同一查詢的numberOfRecords: 錯誤訊息(19004)startRecord には 1 から検索件数までの値を指定してください。中的「搜尋筆數」指的是同一查詢下的numberOfRecords(實測結果,官方規格未明確說明)。若根據不同查詢(例如未加上from/until的簡單搜尋、單獨使用speakervs 併用、或過去取得的快取值)所取得的筆數來決定startRecord,就可能觸發 19004 錯誤。要進行原因釐清,請針對同一查詢發送一個startRecord=1&maximumRecords=1的請求,重新確認numberOfRecords。這種情況在項目 8 的交集操作或加上from/until導致筆數減少時經常發生(詳細請參閱 api-reference.md 中的 19004 說明)。
常用搜尋模式範例
議員特定時期內的發言
bash scripts/search-by-speaker.sh 石破茂 2024-10-01 2024-10-31 100 --sort date-desc
法案審議追蹤(時間序列)
bash scripts/search-by-keyword.sh マイナンバー法 2023-01-01 '' 100 --sort date-asc
抽取內閣總理大臣演說
speakerPosition 參數 wrapper 未支援,因此需要使用 raw curl:
# wrapper 未支援,使用 raw curl
curl -s 'https://kokkai.ndl.go.jp/api/speech?speakerPosition=%E5%86%85%E9%96%A3%E7%B7%8F%E7%90%86%E5%A4%A7%E8%87%A3&nameOfMeeting=%E6%9C%AC%E4%BC%9A%E8%AD%B0&from=2024-01-01&recordPacking=json'
參考人質詢
bash scripts/search-by-role.sh 參考人 2024-01-01 '' 100 --sort date-desc
特定會議的完整議事錄(兩階段)
# 步驟 1: 找出 issueID(nameOfHouse 篩選 wrapper 未支援,因此從列表中手動選擇)
bash scripts/list-meetings.sh 預算委員會 2024-03-01 2024-03-01 50 --sort date-desc
# 步驟 2: 取得完整記錄
bash scripts/fetch-meeting.sh <issueID>
分頁
所有端點通用。
- 將回應中的
nextRecordPosition傳遞給下一次請求的startRecord。 - 判斷最後一頁的方式:
- JSON:
nextRecordPosition的值為null。 - XML:
<nextRecordPosition>元素本身不存在。
- JSON:
- 連續取得資料時,請間隔數秒(速率限制)。
輸出格式
向使用者呈現發言時的建議格式:
【發言者】○○○○(所屬黨派・職稱)
【會議】第XXX屆國會 眾議院 ○○委員會 第X號(YYYY-MM-DD)
【發言】
發言本文引用(將 CRLF 正規化為換行)
【出處】國會會議記錄搜尋系統 https://kokkai.ndl.go.jp/txt/<issueID>/<speechOrder>
呈現會議列表時:
【會議列表】N 筆
- YYYY-MM-DD: 第XXX屆國會 眾議院 ○○委員會 第X號
https://kokkai.ndl.go.jp/txt/<issueID>
- ...
需要 raw curl 的情況
以下參數 wrapper script 未涵蓋。必要時,請直接使用 curl / Invoke-RestMethod 呼叫 API:
sessionFrom/sessionTo(以屆次篩選)contentsAndIndex/supplementAndAppendix(目次・索引・附錄)closing=true(僅限閉會中審查)nameOfHouse/nameOfMeeting等次要篩選條件(未包含在 wrapper 的參數中)- 分頁(連續呼叫
startRecord+nextRecordPosition) - 同時指定
any與speaker(用於議員本人的自我提及等,刻意利用兩者交集的用途。詳細請參閱 recipes/speaker-vs-any-disambiguation.md 模式 3)
範例:僅抽取第 213 屆國會的預算委員會(需要使用 sessionFrom/sessionTo,wrapper 未支援)
curl -s 'https://kokkai.ndl.go.jp/api/meeting_list?sessionFrom=213&sessionTo=213&nameOfMeeting=%E4%BA%88%E7%AE%97%E5%A7%94%E5%93%A1%E4%BC%9A&maximumRecords=30&recordPacking=json'
對於使用 WebFetch 等內建摘要模型的工具,已觀察到它們會將回應中不存在的欄位作為幻覺(hallucination)混入,因此不應用於取得原始資料(詳細請參閱 response-format.md)。
詳細參考資料
- api-reference.md: 端點規格・分頁・錯誤回應
- parameters.md: 搜尋參數的完整規格・搜尋方式・組合範例
- response-format.md: 回應結構・實際 JSON 範例・實測基礎的陷阱
- recipes.md: 複合模式集(議員 × 關鍵字篩選等,scripts 無法涵蓋的案例)