news-API / app.py
matsuap's picture
Enhance news fetching functionality with language support and update UI for multilingual input options.
ae968de
import gradio as gr
import requests
import pandas as pd
from dotenv import load_dotenv
import os
load_dotenv()
# NewsAPI設定
NEWS_API_URL = os.getenv("NEWS_API_URL")
API_KEY = os.getenv("API_KEY")
def fetch_news(query="ecolab", sort_by="publishedAt", page_size=10, language="auto"):
"""
NewsAPIからニュース情報を取得する関数
"""
try:
# NewsAPIの正しいヘッダー形式
headers = {
"X-API-Key": API_KEY,
"User-Agent": "NewsApp/1.0"
}
# 日本語検索の場合は日本語も含める
params = {
"q": query,
"sortBy": sort_by,
"pageSize": page_size,
}
# 言語設定を動的に決定
if language == "all":
# すべての言語で検索(言語制限なし)
pass
elif language == "jp":
# 日本語のソースも含めるため、言語制限を外すか日本語圏のソースを指定
pass # NewsAPIの日本語サポートは限定的なので制限を外す
elif language == "en":
params["language"] = "en"
elif language == "auto":
# 日本語文字が含まれている場合は言語制限を外す
if any('\u3040' <= char <= '\u309F' or '\u30A0' <= char <= '\u30FF' or '\u4E00' <= char <= '\u9FAF' for char in query):
pass # 言語制限なしで検索
else:
params["language"] = "en"
response = requests.get(NEWS_API_URL, headers=headers, params=params)
if response.status_code == 200:
data = response.json()
if data["status"] == "ok" and data["totalResults"] > 0:
articles = data["articles"]
# データを整理
news_data = []
for article in articles:
news_data.append({
"タイトル": article.get("title", "N/A"),
"説明": article.get("description", "N/A"),
"ソース": article.get("source", {}).get("name", "N/A"),
"公開日": article.get("publishedAt", "N/A"),
"URL": article.get("url", "N/A")
})
# DataFrameに変換
df = pd.DataFrame(news_data)
return df, f"✅ {len(articles)}件のニュースを取得しました"
else:
return pd.DataFrame(), "❌ ニュースが見つかりませんでした"
else:
return pd.DataFrame(), f"❌ APIエラー: {response.status_code} - {response.text}"
except Exception as e:
return pd.DataFrame(), f"❌ エラーが発生しました: {str(e)}"
def search_news(query: str, sort_by: str, page_size: int, language: str = "auto"):
"""
Main function for searching news.
Args:
query (str): The search keyword for news articles.
sort_by (str): The sorting method for the news results.
page_size (int): The number of news articles to retrieve.
language (str): Language for search results.
Returns:
tuple: DataFrame and status message
"""
if not query.strip():
return pd.DataFrame(), "❌ 検索キーワードを入力してください"
df, message = fetch_news(query, sort_by, page_size, language)
return df, message
# Gradioインターフェース
with gr.Blocks(title="📰 News API アプリ", theme=gr.themes.Soft()) as demo:
gr.Markdown(
"""
# 📰 News API ニュース検索アプリ
NewsAPIを使用してリアルタイムのニュース情報を検索・取得できます。
**🔥 日本語検索対応!**
**使い方:**
1. 検索キーワードを入力(日本語・英語両方対応)
2. 言語とソート方法を選択
3. 取得件数を選択
4. 「ニュース検索」ボタンをクリック
"""
)
with gr.Row():
with gr.Column():
# 入力コンポーネント
query_input = gr.Textbox(
label="🔍 検索キーワード",
placeholder="例: 東京, トヨタ, AI, ecolab, technology...",
value="ecolab"
)
language_dropdown = gr.Dropdown(
choices=[
("自動検出", "auto"),
("日本語", "jp"),
("英語", "en"),
("すべての言語", "all")
],
label="🌐 言語",
value="auto"
)
sort_by_dropdown = gr.Dropdown(
choices=["publishedAt", "relevancy", "popularity"],
label="📊 ソート方法",
value="publishedAt"
)
page_size_slider = gr.Slider(
minimum=5,
maximum=50,
value=10,
step=5,
label="📄 取得件数"
)
search_btn = gr.Button("🔍 ニュース検索", variant="primary")
with gr.Column():
# 出力コンポーネント
status_output = gr.Textbox(
label="📋 ステータス",
interactive=False
)
# 結果表示
results_df = gr.Dataframe(
label="📰 ニュース結果",
wrap=True,
row_count=30,
interactive=False
)
# イベントハンドラー
search_btn.click(
fn=search_news,
inputs=[query_input, sort_by_dropdown, page_size_slider, language_dropdown],
outputs=[results_df, status_output],
show_api=True,
)
# Enter キーでも検索可能
query_input.submit(
fn=search_news,
inputs=[query_input, sort_by_dropdown, page_size_slider, language_dropdown],
outputs=[results_df, status_output],
show_api=False,
)
# 初期ロード時にデフォルト検索を実行
demo.load(
fn=lambda: search_news("ecolab", "publishedAt", 10, "auto"),
outputs=[results_df, status_output],
show_api=False,
)
# アプリ起動
if __name__ == "__main__":
demo.launch(mcp_server=True)