FastAPIで作るGNews APIサーバー:構築から使い方までの備忘録

PythonのFastAPIとGNews APIを使って、ニュース検索サーバーを構築・利用する手順をまとめた備忘録です。

主な機能からAPIの使い方までのメモです。

目次

主な機能

このサーバーでできることのまとめ。

  • サーバーのヘルスチェック: サーバーが問題なく動いているかを確認する。
  • キーワードによる記事検索: 好きなキーワードでニュース記事を検索する。
  • トップニュースの取得: 指定したカテゴリの話題のニュースを取得する。

必要なものと準備

サーバーを動かす前に必要なライブラリと設定。

フォルダ構成

- gnews_fast_api.py
- requirements.txt
- .env

1.必要なライブラリのインストール

requirements.txt というファイルに以下の内容を記述する。

fastapi
uvicorn[standard]
requests
python-dotenv
gnews

その後、ターミナルで以下のコマンドを実行して一括インストールする。

pip install -r requirements.txt

2. GNews APIキーの取得と設定

ニュースデータの取得には GNews API を利用する。

  1. APIキーの取得: GNews公式サイト でユーザー登録し、APIキーを手に入れる。
  2. .envファイルの作成: プロジェクトのルートディレクトリ(gnews_fast_api.py と同じ場所)に .env ファイルを作成し、取得したAPIキーを以下のように記述する。
# .envファイル
GNEWS_API_KEY="ここにあなたのGNews APIキーを貼り付けます"

これで、サーバー起動時にAPIキーが自動で読み込まれる。

3.プログラム

# gnews_fast_api.py (ファイル名)

import os
import sys
import json
from enum import Enum
from typing import List, Dict, Any, Optional

import requests
import uvicorn
from dotenv import load_dotenv
from fastapi import FastAPI, Query, HTTPException

# .envファイルから環境変数を読み込む
load_dotenv()

# --- GNews API クライアントクラス (元のコードをほぼそのまま利用) ---
class GNewsClient:
    """
    GNews APIを扱うためのクライアントクラス。
    """
    BASE_URL = "https://gnews.io/api/v4"

    def __init__(self, api_key: Optional[str]):
        """
        APIキーを引数として受け取る。
        """
        if not api_key:
            raise ValueError("エラー: 環境変数 'GNEWS_API_KEY' が設定されていません。")
        self.api_key = api_key

    def _make_request(self, endpoint: str, params: Dict[str, Any]) -> List[Dict[str, Any]]:
        """
        GNews APIへのリクエストを共通して処理する内部メソッド。
        """
        url = f"{self.BASE_URL}/{endpoint}"
        params["apikey"] = self.api_key
        request_params = {k: v for k, v in params.items() if v is not None}
        
        try:
            response = requests.get(url, params=request_params)
            response.raise_for_status()  # HTTPエラーがあれば例外を発生
            data = response.json()
            return data.get("articles", [])
        except requests.exceptions.HTTPError as e:
            # APIからのエラーを捕捉し、より詳細な例外として再送出
            status_code = e.response.status_code
            error_detail = e.response.json()
            raise HTTPException(status_code=status_code, detail=error_detail)
        except requests.exceptions.RequestException as e:
            # 接続エラーなど
            raise HTTPException(status_code=503, detail=f"Service Unavailable: {e}")

    def search(self, **kwargs) -> List[Dict[str, Any]]:
        """キーワード検索を実行"""
        return self._make_request("search", kwargs)

    def get_top_headlines(self, **kwargs) -> List[Dict[str, Any]]:
        """トップニュースを取得"""
        return self._make_request("top-headlines", kwargs)

# --- FastAPI アプリケーションの定義 ---

# FastAPIのインスタンスを作成
app = FastAPI(
    title="GNews Search API",
    description="GNews APIを利用してニュース記事を検索・取得するためのサーバーです。",
    version="1.0.0",
)

# GNewsClientのインスタンスを作成 (サーバー起動時に一度だけ実行)
try:
    gnews_client = GNewsClient(api_key=os.getenv("GNEWS_API_KEY"))
except ValueError as e:
    print(f"致命的エラー: {e}", file=sys.stderr)
    sys.exit(1)

# --- パラメータ用のEnumを定義 (これによりAPIドキュメントで選択肢が表示される) ---
class Category(str, Enum):
    general = "general"
    world = "world"
    nation = "nation"
    business = "business"
    technology = "technology"
    entertainment = "entertainment"
    sports = "sports"
    science = "science"
    health = "health"

class SortBy(str, Enum):
    published_at = "publishedAt"
    relevance = "relevance"

class InFields(str, Enum):
    title = "title"
    description = "description"
    content = "content"


# --- API エンドポイントの定義 ---

@app.get("/", summary="サーバーのヘルスチェック")
def read_root():
    """
    サーバーが正常に起動しているか確認するためのエンドポイント。
    """
    return {"status": "ok", "message": "Welcome to GNews Search API!"}


@app.get("/search", summary="キーワードによるニュース記事検索")
def search_articles(
    q: str = Query(..., description="検索キーワード。例: 'Tesla'"),
    lang: Optional[str] = Query('ja', description="言語コード。例: 'en', 'ja'"),
    country: Optional[str] = Query('jp', description="国コード。例: 'us', 'jp'"),
    max: Optional[int] = Query(10, ge=1, le=100, description="最大取得件数 (1-100)"),
    sortby: Optional[SortBy] = Query(None, description="ソート順"),
    in_fields: Optional[InFields] = Query(None, alias="in", description="検索対象フィールド")
):
    """
    指定されたキーワードでニュース記事を検索します。
    - **q**: 検索キーワードは必須です。
    """
    params = {
        "q": q,
        "lang": lang,
        "country": country,
        "max": max,
        "sortby": sortby.value if sortby else None,
        "in": in_fields.value if in_fields else None,
    }
    return gnews_client.search(**params)


@app.get("/top-headlines", summary="トップニュースの取得")
def get_top_news(
    category: Category = Query('general', description="ニュースカテゴリ"),
    q: Optional[str] = Query(None, description="トップニュース内をさらに絞り込むキーワード (オプション)"),
    lang: Optional[str] = Query('ja', description="言語コード"),
    country: Optional[str] = Query('jp', description="国コード"),
    max: Optional[int] = Query(10, ge=1, le=100, description="最大取得件数 (1-100)"),
):
    """
    指定されたカテゴリのトップニュースを取得します。
    """
    params = {
        "category": category.value,
        "q": q,
        "lang": lang,
        "country": country,
        "max": max,
    }
    return gnews_client.get_top_headlines(**params)

# --- サーバー起動用の設定 (開発用) ---
if __name__ == "__main__":
    uvicorn.run("gnews_fast_api:app", host="0.0.0.0", port=8080, reload=True)

サーバーの起動方法

準備が完了したら、ターミナルで以下のコマンドを実行する。

python3 gnews_fast_api.py
  • --reload オプションを付けておくと、コードを修正した際に自動でサーバーが再起動して便利。

サーバーが正常に起動すると、以下のようなログが表示される。

INFO:     Will watch for changes in these directories: ['/usr/src/app']
INFO:     Uvicorn running on http://0.0.0.0:8080 (Press CTRL+C to quit)
INFO:     Started reloader process [25] using WatchFiles
INFO:     Started server process [27]
INFO:     Waiting for application startup.
INFO:     Application startup complete.

Swagger UIで動作確認

サーバー起動後、Webブラウザで http://localhost:8080/docs にアクセスする。

FastAPIが自動生成するAPIドキュメント画面(Swagger UI)が表示される。ここから直接APIの動作テストができるので非常に便利。

/Searchエンドポイントでテスト

取得結果
[
  {
    "id": "a0e710b3313726e447e71d2dc0ced24c",
    "title": "ゲーム開発にてイラスト生成AIはどのように使えるか?『MapleStory Worlds』開発スタッフによって研究されたAIの可能性、そして限界点【NDC25】",
    "description": "本稿では「『MapleStory Worlds』 AI R&D」セッションの模様をお届けします。",
    "content": "ネクソンは、2025年6月24日から26日にかけて「Nexon Developers Conference 2025(NDC)」を韓国にて開催しました。NDCは『メイプルストーリー』『ブルーアーカイブ』『デイヴ・ザ・ダイバー』などを手掛けるネクソングループをはじめとして、第一線の開発者らが集まり知識の共有を図るカンファレンスです。\n本稿では「『MapleStory Worlds』 AI R&D」セッションの模様をお届けしていきます。『MapleStory Worlds』は『メイプルストーリー』I... [2165 chars]",
    "url": "https://www.inside-games.jp/article/2025/07/08/169261.html",
    "image": "https://www.inside-games.jp/imgs/ogp_f/1601548.jpg",
    "publishedAt": "2025-07-08T12:30:03Z",
    "source": {
      "id": "4a610d8a06b22cf4bf0add8a41b9f913",
      "name": "インサイド",
      "url": "https://www.inside-games.jp"
    }
  },
  {
    "id": "6f2ebd1c40c7dcdbb65f371e959e7922",
    "title": "ゴールドマン・サックス、生成AIアシスタント導入で人員削減",
    "description": "AIがここまでできると、人間ももっとスキルアップしないといけないかも。2025年6月25日、ウォール街の大手投資銀行・Goldman Sachs(ゴールドマン・サックス)が社内向けに生成AIアシスタントを正式に導入したことを発表しました。大手投資銀行が業務効率化のため、生成AIを導入へ同社のAIアシスタントは対話型のAIインターフェースを採用。1年以上にわたって社内開発とテストを行ない、1万人を",
    "content": "AIがここまでできると、人間ももっとスキルアップしないといけないかも。\n2025年6月25日、ウォール街の大手投資銀行・Goldman Sachs(ゴールドマン・サックス)が社内向けに生成AIアシスタントを正式に導入したことを発表しました。\n大手投資銀行が業務効率化のため、生成AIを導入へ\n同社のAIアシスタントは対話型のAIインターフェースを採用。1年以上にわたって社内開発とテストを行ない、1万人を超える従業員がこのツールのパイロット運用に参加してきました。\nまたこのAIアシスタントは独自の厳... [1790 chars]",
    "url": "https://www.gizmodo.jp/2025/07/goldman-sachs-makes-a-huge-ai-bet.html",
    "image": "https://media.loom-app.com/gizmodo/dist/images/2025/07/02/shutterstock_2427065215.jpg?w=1280&h=630&f=jpg",
    "publishedAt": "2025-07-02T03:30:00Z",
    "source": {
      "id": "4609d947e914f80baf7d9cbbf3958178",
      "name": "ギズモード・ジャパン",
      "url": "https://www.gizmodo.jp"
    }
  },
  {
    "id": "541af747d982e2ed3bacae026d472ea9",
    "title": "NBAファイナル中に放送されたAI生成広告、VEO 3を使い2日で作成",
    "description": "Google(グーグル)の動画生成AI「VEO 3」で生成された動画がありとあらゆるメディアに溢れ始めています。5月に開催されたGoogle I/O 2025(デベロッパ向けカンファレンス)で発表された直後から、YouTuberの街頭インタビューからガジェット開封動画、実在しないゲームの実況動画、など、360度のVR再現動画ありとあらゆるジャンルの動画が登場。どんなにおもしろいものでも、くだらな",
    "content": "Google(グーグル)の動画生成AI「VEO 3」で生成された動画がありとあらゆるメディアに溢れ始めています。\n5月に開催されたGoogle I/O 2025(デベロッパ向けカンファレンス)で発表された直後から、YouTuberの街頭インタビューからガジェット開封動画、実在しないゲームの実況動画、など、360度のVR再現動画ありとあらゆるジャンルの動画が登場。どんなにおもしろいものでも、くだらないものでも、目を覆いたくなるようなものでも、生成AI動画はある意味「低リスク」でした。\nでも今回はア... [1872 chars]",
    "url": "https://www.gizmodo.jp/2025/06/googles-veo-3-ai-slopfest-just-reached-new-heights.html",
    "image": "https://media.loom-app.com/gizmodo/dist/images/2025/06/20/20250620_veo3-2.jpg?w=1280&h=630&f=jpg",
    "publishedAt": "2025-06-23T03:30:00Z",
    "source": {
      "id": "4609d947e914f80baf7d9cbbf3958178",
      "name": "ギズモード・ジャパン",
      "url": "https://www.gizmodo.jp"
    }
  }
]

/top-headlinesエンドポイントでテスト

取得結果
[
  {
    "id": "c4acf7143b9d05a1fa0faa0168566051",
    "title": "AMD、AI開発向けGPU「Radeon AI PRO R9700」をワークステーション向けに提供開始",
    "description": "AMDは、人工知能(AI)開発および高スループット推論向けに特化した最新のプロフェッショナル向けビデオスカード「AMD Radeon AI PRO R9700」を発表した。本GPUは、大手システムインテグレーター(SI)パートナー製のワークステーションへの搭載から提供が開始される。",
    "content": "AMDは、人工知能(AI)開発および高スループット推論向けに特化した最新のプロフェッショナル向けビデオスカード「AMD Radeon AI PRO R9700」を発表した。本GPUは、大手システムインテグレーター(SI)パートナー製のワークステーションへの搭載から提供が開始される。\n大規模AIモデル処理に強みを発揮する32GB VRAM\n近年のAI技術の進化に伴い、大規模な言語モデル(LLM)や生成系AIといった複雑なAIモデルの処理には、膨大なメモリー容量が求められる。Radeon AI PR... [1440 chars]",
    "url": "https://ascii.jp/elem/000/004/303/4303316/",
    "image": "https://ascii.jp/img/2025/07/19/4296609/xl/a7945fc6308f1cf6.jpg?20200122",
    "publishedAt": "2025-07-18T23:00:00Z",
    "source": {
      "id": "4b4d745971f48912bcad9062fb9060c9",
      "name": "ASCII.jp",
      "url": "https://ascii.jp"
    }
  },
  {
    "id": "4122924c8917ff7ce52c720a647346b9",
    "title": "Pixel向けAndroid 16 QPR1 Beta 3公開。安定性向上へ最後の磨き上げ、9つの主要バグ修正とユーザー待望のUI改善",
    "description": "Googleは2025年7月17日(現地時間)、Pixelデバイス向けに「Android 16 QPR1 Beta 3」の配信を開始した。9月に予定されている安定版の正式リリースを前に、これが最後のベータ版となる見込みだ。",
    "content": "Googleは2025年7月17日(現地時間)、Pixelデバイス向けに「Android 16 QPR1 Beta 3」の配信を開始した。9月に予定されている安定版の正式リリースを前に、これが最後のベータ版となる見込みだ。\n今回のアップデートは、派手な新機能の追加よりも、システムの安定性向上とバグ修正に主眼が置かれている。特に、予期せぬ再起動やランチャーの表示不良といった深刻な問題を含む9つの主要な不具合が修正されており、まさに安定版に向けた「最後の磨き上げ」というべき内容だ。\nさらに、一部ユー... [4010 chars]",
    "url": "https://xenospectrum.com/android-16-qpr1-beta-3-for-pixel-released/",
    "image": "https://xenospectrum.com/wp-content/uploads/2025/06/android-16-release.png",
    "publishedAt": "2025-07-18T19:52:46Z",
    "source": {
      "id": "ce09834ae051142fbd166609e9fdaee8",
      "name": "XenoSpectrum",
      "url": "https://xenospectrum.com"
    }
  },
  {
    "id": "88b0ad4b71e4394cc81ae871b71e7b16",
    "title": "TSMC、第2四半期は過去最高益 AI需要寄与し予想上回る",
    "description": "半導体受託生産世界最大手の台湾積体電路製造(TSMC) が17日発表した第2・四半期決算は、純利益が60.7%急増し過去最高を記録した。市場予想を大幅に上回る結果となったが、米国の関税措置と台湾ドル高が今後の見通しに影を落とす可能性がある。",
    "content": "半導体受託生産世界最大手の台湾積体電路製造(TSMC) が7月17日発表した第2・四半期決算は、純利益が60.7%急増し市場予測を上回った。写真は同社のロゴ。6月7日、台湾・高雄市の製造工場で撮影(2025年 ロイター/Ann Wang)\n半導体受託生産世界最大手の台湾積体電路製造(TSMC) が7月17日発表した第2・四半期決算は、純利益が60.7%急増し市場予測を上回った。写真は同社のロゴ。6月7日、台湾・高雄市の製造工場で撮影(2025年 ロイター/Ann Wang)\n第2・四半期(4ー6... [287 chars]",
    "url": "https://jp.reuters.com/markets/world-indices/3YEII4L72BIINF4VMRAMCITMGA-2025-07-17/",
    "image": "https://www.reuters.com/resizer/v2/KSR5A2CO6JMYJEXOZMO4XOEDCM.jpg?auth=f4c1139949799bd7f10d0552a86ed64cc447a696afcc07fad589c089d4a43ab1&height=1005&width=1920&quality=80&smart=true",
    "publishedAt": "2025-07-17T05:56:00Z",
    "source": {
      "id": "31280eb773ec58b2d5348fe891a1cb8d",
      "name": "Reuters",
      "url": "https://jp.reuters.com"
    }
  }
]

コードのアーキテクチャに関するメモ

コードの構造についての簡単なメモ。

  • GNewsClient クラス:
    • GNews APIとの通信に関する処理をすべてこのクラスにまとめている。
    • APIキーの管理やリクエストの送信、エラーハンドリングなどを担当。
  • FastAPI アプリケーション (app):
    • APIのエンドポイント(URL)を定義する部分。
    • @app.get(...) という記述で、どのURLにアクセスされたらどの関数を実行するかを指定している。
    • FastAPIの機能により、関数の引数を定義するだけで、パラメータの検証やAPIドキュメントの自動生成が行われる。
  • Enum によるパラメータ定義:
    • Category のように、決まった選択肢の中から値を選ぶパラメータは Enum で定義。
    • これにより、想定外の値が入力されるのを防ぎ、APIドキュメント上では選択式のプルダウンで表示されるため使いやすい。

まとめ

このドキュメントは、GNews APIをFastAPIサーバーから利用するための手順と仕様をまとめた備忘録です。

堅牢なエラーハンドリングと開発者フレンドリーな設計を備えており、ニュース関連アプリケーションのプロトタイピングや、より大規模なシステムへの組み込みなど、様々な用途で活用できるでしょう。

よかったらシェアしてね!
  • URLをコピーしました!
  • URLをコピーしました!
目次