WebAPI。ニュースを取得する。JSONで返る。2019-09-16時点の調査。
成果物
情報源
上記のように記せと言われたので書いておく。
手順
ニュースの取得
NewsAPIにてニュース記事を取得できるらしい。ただ、結果のJSONを見てみると、本文をすべて取得できるわけではなさそう。URL先をみる必要がある。つまり、本文の全文はHTMLスクレイピングによって抽出せねばならない。それに関しては今回はやらない。
価格プラン
もちろん無料の「開発者」プラン。
- 15分遅れ
- 1ヶ月前までの記事のみ
- 500回リクエスト/1日
- NewsAPI.orgの帰属表示(Powerd by News API)
利用規約
SLA(サービスレベル契約)
各プランのサービスレベルを達成および維持しない場合、将来の月額サービス料金に対して25%のクレジットを受け取る資格があります。
毎月の稼働率%=(合計リクエスト試行-失敗したリクエスト)/合計リクエスト試行* 100
たぶん価格プラン「企業」の場合に関係する。99.95%の稼働時間SLA
と書いてあったから。無料プランの「開発者」はアップタイムSLAなし
とあった。おそらく関係ないのだろう。
だが、もしかすると将来「お前、以前こんなに何度も使ったよな? あのときの超過分25%を支払えよ」と言われるかもしれない。
- 英語読めないし、文化や法律の違いなど、どんな理由で後出し難癖つけられるかわからない
- リクエスト上限もいずれ改悪されて少なくなるかも
- 時が経ち、忘れたアカウントをハックをされて勝手にリクエストされ、請求だけされるかも
念のため1日1回くらいにしておこう。
スタートガイド
curl https://newsapi.org/v2/top-headlines -G \ -d country=jp \ -d apiKey=****
ドキュメント
認証
curl https://newsapi.org/v2/top-headlines -G \ -d country=jp \ -H 'X-Api-Key:****'
curl https://newsapi.org/v2/top-headlines -G \ -d country=jp \ -H 'Authorization: Bearer ****'
apiKey
より上記のほうがセキュリティ高いので推奨。
エンドポイント
内容 | エンドポイント |
---|---|
トップ | /v2/top-headlines |
すべて | /v2/everything |
ソース | /v2/sources |
トップの主な引数
トップニュースを取得できれば良いだろう。主な引数は以下。
引数 | 値 |
---|---|
country |
ja |
categoly |
business entertainment general health science sports technology |
source |
source index。country ,categoly と併用不可。 |
pagesize |
デフォルト20 。最大100 。今回はなぜか30件までしか取得できず |
page |
ページ位置 |
q |
キーワード |
コード
ファイルがあるかぎり1日1回しか実行しない。
run.sh
get_news_api_key() { cat "${HOME}/root/work/record/pc/account/newsapikey"; } request() { NEWS_API_KEY="${NEWS_API_KEY:-"`get_news_api_key`"}" curl https://newsapi.org/v2/top-headlines -G \ -d country=jp \ -d pageSize=100 \ -H "X-Api-Key:${NEWS_API_KEY}" } # $1: NewsApi結果JSONファイルパス is_run() { [ ! -f "$1" ] && echo 'true' || is_not_today "$1"; } # $1: NewsApi結果JSONファイルパス is_not_today() { # ファイルが存在し、更新日時が今日なら falseを返す updated="`date +"%Y-%m-%d" -r "$1"`" [ "$updated" = "`date +"%Y-%m-%d"`" ] && echo 'false' || { rename_file "$1"; echo 'true'; } } # $1: NewsApi結果JSONファイルパス format_json() { local name="_`basename "$1"`" local dir="`dirname "$1"`" cat "$1" | python3 -c 'import sys,json;print(json.dumps(json.loads(sys.stdin.read()),indent=4,ensure_ascii=False))' > "${dir%/}/${name}" } # TodayNews.jsonファイルが既存だが更新日時が今日でないときYYYYmmdd.jsonにリネームする。 # $1: NewsApi結果JSONファイルパス rename_file() { local today="`date +"%Y%m%d"`" local updated="`date +"%Y%m%d" -r "$1"`" [ "$updated" != "$today" ] && mv "$1" "${updated}.json" } run() { local TODAY_NEWS="${TODAY_NEWS:-TodayNews.json}" [ 'false' = "`is_run "${TODAY_NEWS}"`" ] && exit 1; echo "`request`" > "${TODAY_NEWS}" format_json "${TODAY_NEWS}" cat "${TODAY_NEWS}" } run
- APIキー
- 入出力ファイル
- 整形ファイル
_TodayNews.json
ファイルはスペースや改行で見やすくなっている。確認用。
- 過去ファイル
- 以前の
TodayNews.json
ファイルは変更日時に基づいてリネームされる
- 以前の
実行
取得できたが、100件でなく30件しか取得できない……。以下では20件のみだったらしい。
どうやらNewsApi側で制限しているようだ。/v2/top-headlines
は30件までしか取得でいないのだろう。100
が上限と書いてあるのに。騙された。
対して/v2/everything
なら100件取得できるらしい。本当かな。
問題
- 30件までしか取得できない
- ニュースのカテゴリが指定できていない
- 今日のニュースだけでなく前日の分まで出る
- 時間によっては過去に取得したものと重複する
特に最後のが問題。取得した時間にかかわらず、重複なく取得したい。
さらに以下のような根本的な問題もある。
- いつかサービス終了する
別のAPIを複数使うことでリスク分散したい。APIを切り替えれるような設計にしたい。その上で、同一インタフェースによりアクセスできるのが望ましい。
これは大変そうだ。各社ばらばらのURLやパラメータやJSONなので。
対象環境
- Raspbierry pi 3 Model B+
- Raspbian stretch 9.0 2018-11-13
- bash 4.4.12(1)-release
$ uname -a Linux raspberrypi 4.19.42-v7+ #1218 SMP Tue May 14 00:48:17 BST 2019 armv7l GNU/Linux