LoginSignup
0
0

More than 1 year has passed since last update.

2022NHKハッカソン 防災編に出て、災害を学べるコンテンツを返すアプリを作った

Last updated at Posted at 2022-11-17

10月にNHKハッカソン 防災編に参加しました。

ハッカソン自体への参加がはじめてでした(多分)。イベント自体は、いろいろな方が参加されており、アイデアを聞いているだけでも楽しめました。

一応手も動かしたいということで、チームで作った「災害の学習に役立つNHKコンテンツのCSVファイル」を使って、それをランダムに返すアプリを作成しました。

イベントは様々な方と作業ができて、凄い楽しかったです。この記事は、参加記録兼作ったもののメモです(遅いけどw。

概観

--- 開発環境 ---
WSL2
python 3.8.10
dash 2.6.2
flask 2.2.2
    --------

アプリの構造的にはFlaskでランダムにニュースのURLを返すAPIを作って、それをDashで描画します。

DashはPythonのReactラッパーみたいな存在で、お手軽に使えるので、使いました。

アプリはヘロクの無料枠で動いており、11月28日に動かなくなる見込みです。
https://nhk-hackathon-front.herokuapp.com/

Image from Gyazo

API

APIはFlaskを使って作りました。普段はデータ分析ばかりしているので、あまりAPIとか作りませんが、Flaskはちょっと触ったことがあったので、簡単に作成できました。

コードとデータはリンク先のリポジトリに置いてあります。今見たらvenvディレクトリが入りっぱなし。修正しておきます。
https://github.com/mazarimono/nhk-hackathon

ここでは、dataディレクトリにnhk-news.csvを置いています。

そのファイルをpandasを使って読み込み、データフレームの列数を数えたあと、ランダムな数値を生成し、ニュースのタイトルとURLを返します。

from flask import Flask
import pandas as pd
import random

@app.route('/api/v0/news/random_news')
def return_randomnews():
    df = pd.read_csv('data/nhk-news.csv')
    random_int = random.randrange(0, len(df))
    rand_df = df.iloc[random_int, :]
    news_title = rand_df.loc['タイトル']
    news_url = rand_df.loc['URL']
    return {
        'news_title': news_title,
        'news_url': news_url
    }

フロント

フロントでは、Dashのコールバックで先ほど作成したAPIを叩いてニュースのリンクを呼び出して描画しています。

工夫した点はボタンのn_clicks属性の初期値を1にしたうえで、コールバックがn_clicks>0で動作するようにした点です。これによりアプリの立ち上がりでもAPIを叩いて、ニュースのリンクが表示されます。

コールバックでは、ボタンが押されるとAPIを叩き、記事のリンクとURLを返します。

再度ボタンが押されると、次のニュースが呼び出されます。
https://github.com/mazarimono/nhk-randomnews

from dash import Dash, html, Input, Output
import dash_bootstrap_components as dbc
import requests


app = Dash(
    "__name__",
    external_stylesheets=[dbc.themes.BOOTSTRAP],
    meta_tags=[
        {"name": "viewport", "content": "width=device-width, initial-scale=1"},
    ],
)
server = app.server


app.layout = html.Div(
    [
        html.Div(
            [
                html.H1("おススメNHK防災コンテンツ", style={"padding": 10}),
                html.H3(id="selected_title"),
                html.A(id="selected_link"),
            ]
        ),
        html.Div(
            [dbc.Button(id="update_button", children="ニュース更新ボタン", n_clicks=1)],
            style={"padding": 30},
        ),
        html.Div(
            [
                dbc.Accordion(
                    [
                        dbc.AccordionItem(
                            [html.P("このサイトは防災について学べるおススメ記事のリンクを、ランダムにおススメします")],
                            title="サイトの説明",
                        )
                    ],
                    start_collapsed=True,
                    style={"width": "80%", "margin": "auto"},
                ),
            ]
        ),
    ],
    style={"textAlign": "center", "padding": 10},
)


@app.callback(
    Output("selected_title", "children"),
    Output("selected_link", "href"),
    Output("selected_link", "children"),
    Input("update_button", "n_clicks"),
)
def update_news(n_clicks):
    if n_clicks > 0:
        r = requests.get("https://nhk-hackathon.herokuapp.com/api/v0/news/random_news")
        news_title = r.json()["news_title"]
        news_url = r.json()["news_url"]
        return news_title, news_url, news_url
    else:
        pass


if __name__ == "__main__":
    app.run_server(debug=True)

まとめ

以上のようなアプリを作って、NHKさんの防災に役立つ記事が読めるアプリを作成してみました。NHKさんにはたくさんのアセットがあるそうなので、APIとか作られると色々楽しそうですね!

私はこのアプリを使って、CSVファイルにある記事をたまに読んで、防災学習をしています。

最後に、ハッカソンの開催ありがとうございました!

csvをランダムに吐き出すのはDashのみでもできるのですが、チームのアプリでこのような機能を使いたかったのでAPIを作成しました。このアプリでもそのAPIを使ったらええやんと思い、こんかいのようなかたちとなっております。

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0