ビジネスパーソン・ガジェット置場 empty lot for business

営業や仕事、それに伴う生活を便利に楽にするツール、ガジェットを作ります。既にあるツールも自分用にカスタマイズ。

ニュース一覧アプリ【OpenWeatherAPI/NewsAPI,/YoutubeAPI】

いろんなAPIを複合して自分の好きなものを表示するようにしたガジェットです。今回はヘッドラインニュースと動画、そして天気をまとめてみました。

f:id:kslabo51:20220330195050j:plain

例えばこんな状況で

今回のガジェットはこういう声に対応
「ニュースあぷりなどはいろんな情報が溢れすぎていてついつい余計なものまで見てしまい、元々知りたかった情報がなんだっけってなります。自分の好きな情報だけまとめれるようになるといいなと」

f:id:kslabo51:20220330195145p:plain

このガジェットでできることはこちら

  • 今回はニュース・天気予報・youtube動画を取得できるようにしました。
  • ヘッドラインニュースを検索ワードから取ってきます。
  • また検索ワードから関連youtube動画を取ってきます。
  • そしてyoutube動画自体を同じ画面で見ることが可能です。
  • あとは天気の情報も入れてみました。

注意点はこちら

  • UI自体はstreamlitでシンプルにしており簡素な作りになっています。

評価(自己)

役立ち度  ★★★★(良し)
効率化   ★★★(平均)
ミス防止  ★★★(平均)
楽しさ   ★★★(平均)
操作    ★★★(平均)

※画面の作りはもう少し楽しくできたら良いと思います。

 

実行環境

使用環境    streamlit、OpenWeatherAPI、NewsAPI, YoutubeAPI 
使用言語    python
使用ライブラリ    requests、json、pandas、PIL、streamlit、datetime、  

        googleapiclient.discovery

 

コード

import requests
import json
import pandas as pd
from PIL import Image
import streamlit as st
import datetime as dt
from googleapiclient.discovery import build

st.title('My News App')

with open('info.json', 'r') as f:
    key = json.load(f)
    
with open('secret.json') as f:
    secret = json.load(f)
    
headers = {'X-Api-Key': key['API_KEY']}
weather_key = key['W_API_KEY']
DEVELOPER_KEY = secret['API_KEY']
YOUTUBE_API_SERVICE_NAME = "youtube"
YOUTUBE_API_VERSION = "v3"

youtube = build(YOUTUBE_API_SERVICE_NAME, YOUTUBE_API_VERSION, developerKey=DEVELOPER_KEY)


def upload_news(q_word, category):
    head_url = 'https://newsapi.org/v2/top-headlines'

    params = {
        'category': category,
        'country': 'jp',
        'q': q_word
    }

    res = requests.get(head_url, headers=headers, params=params)

    headline_data = res.json()
    
    l = []
    for article in headline_data['articles']:
        _df = {}
        _df['タイトル'] = article['title']
        _df['ニュース'] = article['description']
        _df['著者'] = article['author']
        _df['url'] = article['url']
        _df['イメージ'] = article['urlToImage']
        l.append(_df)
    df = pd.DataFrame(l)
    return df

def video_search(youtube, q='自動化', max_results=50):
    # 検索
    response = youtube.search().list(
        q=q,
        part="id,snippet",
        order='viewCount',
        type='video',
        maxResults=max_results
    ).execute()

    items_id = []
    items = response['items']
    for item in items:
        item_id ={}
        item_id['タイトル'] = item['snippet']['title']
        item_id['動画ID'] = item["id"]["videoId"]
        item_id['チャンネルId'] = item['snippet']['channelId']
        items_id.append(item_id)

    df_video = pd.DataFrame(items_id)

    return df_video


def upload_weather(lat, lon):
    w_url = f'https://api.openweathermap.org/data/2.5/onecall?lat={lat}&lon={lon}&exclude=daily&units=metric&lang=ja&appid={weather_key}'
    
    res = requests.get(w_url)
    weather_data = res.json()
    _df = dict(日付 = dt.datetime.fromtimestamp(weather_data['current']['dt']).strftime('%Y/%m/%d'),
        天気 = weather_data['current']['weather'][0]['description'],
        温度 = str(weather_data['current']['temp']) + '℃',
        湿度 = str(weather_data['current']['humidity']) + '%',
        風速 = str(weather_data['current']['wind_speed']) + 'm/s',
        日出 = dt.datetime.fromtimestamp(weather_data['current']['sunrise']).strftime('%H:%M'),
        日入 = dt.datetime.fromtimestamp(weather_data['current']['sunset']).strftime('%H:%M'))
    weather_df = pd.DataFrame(index=_df.keys())
    weather_df['今日'] = _df.values()
    
    icon = weather_data['current']['weather'][0]['icon']
    icon_url = f'http://openweathermap.org/img/w/{icon}.png'

    hourly_data = pd.DataFrame()
    for hourly in weather_data['hourly']:
        time = dt.datetime.fromtimestamp(hourly['dt']).strftime('%H:%M')
        temp = hourly['temp']
        description = hourly['weather'][0]['description']
        hourly_data[time] = [description, time]
        hourly_data = hourly_data.rename(index={0: '状態', 1:'温度'})

    
    return weather_df, hourly_data, icon_url



# トップニュースフィールド
st.sidebar.write('##### トップニュース検索')
q_word = st.sidebar.text_input('検索ワード', value='大谷翔平')
categories = ['business', 'entertainment', 'general', 'health', 'science', 'sports', 'technology']
category = st.sidebar.selectbox('カテゴリー', index=5, options=categories)

if st.sidebar.button('検索'):
    df = upload_news(q_word, category)

    st.write('#### トップニュース')
    for i in range(df.shape[0]):
        st.write(df['タイトル'][i])
        st.write(df['url'][i])
        st.write(df['著者'][i])

    if df.shape[0] >= 3:
        col1, col2, col3 = st.columns(3)
        with col1:
            st.image(df['イメージ'][0])
        with col2:
            st.image(df['イメージ'][1])
        with col3:
            st.image(df['イメージ'][2])        
    elif df.shape[0] == 2:
        col1, col2 = st.columns(2)
        with col1:
            st.image(df['イメージ'][0])
        with col1:
            st.image(df['イメージ'][1])
    else:
        st.image(df['イメージ'][0])

# 動画フィールド
st.sidebar.write('##### 関連動画検索')
query = st.sidebar.text_input('動画検索ワードを入力してください', '大谷翔平')
df_video = video_search(youtube, q=query, max_results=50)
if st.sidebar.button('動画検索'):
    st.write('##### 動画一覧')
    st.dataframe(df_video)

video_id = st.sidebar.text_input('動画一覧から動画IDをコピペしてください')
url = f'https://youtu.be/{video_id}'

video_field = st.empty()

if st.sidebar.button('動画を表示する'):
    if len(video_id) > 0:
        try:
            video_field.video(url)
        except:
            st.error('エラー')

# 天気フィールド            
st.sidebar.write('##### 今日の天気検索')
areas = ['大阪', '福岡', '大塚']
area = st.sidebar.selectbox('地域選択', index=2, options=areas)
if area == '大阪':
    lat, lon = 34.68639, 135.52
elif area == '福岡':
    lat, lon = 33.60639, 130.41806
elif area == '大塚':
    lat, lon = 35.7317593, 139.7280031
    
if st.sidebar.button('天気チェック'):
    st.write('##### 周辺天気')
    weather_df, hourly_data, icon_url = upload_weather(lat, lon)
    st.image(icon_url)
    st.table(weather_df)
    st.dataframe(hourly_data)