MakeとPythonで作るX(Twitter)自動ニュース配信
こんにちは。今回は「MakeとPythonを使ってX(旧Twitter、以降はXと呼びます)でニュースを自動配信する方法」について解説します。
今回は他の記事と比べると少し重たい作業になっています。ただ、1度乗り切れば応用し放題の内容となってますので、頑張って乗り切りましょう!
先日、X自動ポストの構築手順を公開しました。こちらは『Make』(自動化ツール)と各APIのみを使ったシンプルなシステムとなっています。※今現在も元気に稼働してます。
そんな中、最近なのですがConoHa VPS(レンタルサーバ)を契約しました。「自分が自由に遊べる環境が欲しかった。」と、なんとなく思ったのがきっかけです。
せっかく、自分専用のサーバを持ったのでWebサーバ構築してプログラミングをちょいちょいやり始めるようになりました。(ほんと久々。)
WebサーバにHTTP経由でアクセスできるようになって、ふと思ったのが
Make(自動化ツール)とPython組み合わせたら面白いサービス作れそう!
と考え、その第一弾としてXを使ったニュース自動配信サービスを構築することにしました。
ただ、、、今回のシステム構築をするにあたってWebサーバが必須となります。(MakeとWebサーバをHTTP経由で通信させます)。
自分でサーバを買って構築するのも楽しいのですが、メンテナンス作業の手間を考えるとレンタルサーバがオススメです。中でも、ConoHa VPSの最安プランは月額300円程度のレンタル料金となっており、私自身も安く、快適にサーバを使わせてもらってます。
下のボタンからのお申し込みで1ヶ月間無料となりますので、是非この機会に利用してみてください。
それでは始めていきましょう。
前提条件
今回開発を行った環境は以下となります。
<接続先VPSサーバ情報>
サーバ:ConoHa VPS
OS:Ubuntu22.04
Python:3.10.12
Flask:3.0.2
Apache:2.4.52
ロードマップ
ゴールまでのロードマップを以下に示します。STEP1〜STEP4までは過去記事で解説済みなのでリンクからご確認いただければと思います。今回はSTEP5から丁寧に説明していきます。
Webサーバ構築するためのサーバを契約します。
今回はVSCode(コーデエディタ)とConoHa VPSを接続してを使用してプログラムを書きます。ご自身のPC内でプログラミングができて、ファイルをリモート転送できるのであれば特に必要ない工程となります。
ConoHa VPS内にWebサーバを立ち上げて、HTTP通信を可能にします。また、プログラム資材をWebサーバへ配置する外部からアクセスできるように
・『Make』アカウントの取得
・『X』bot用アカウント及びAPIキー情報の取得
・『News API』APIキー情報の取得
今回、Flaskを使ってPython使ってコードを書いていきます。その後、書いたコードをWebサーバへデプロイしてHTTP経由でアクセスできるようにします。
『HTTP』モジュールを使って『Make』からWebサーバへHTTP経由でアクセスしてニュースの情報を取得します。取得した結果を『X』モジュールに連携してポストします。
各種アカウントやAPIキー情報の取得
事前準備はめんどくさいのですが、1度準備をしてしまえばあとはずっと使いまわしができるのでサクッとやってしまいましょう。
『Make』アカウントの取得
今回も『Make』を使ってシステム構築をしていきますのでアカウント作成してください。
※上記から登録すると、今なら1ヶ月間無料でProプランを利用できます。お試しにはちょうど良いかと思います。また、課金登録をしない限り、料金が請求されることはありませんのでご安心ください。
『X』bot用アカウント及びAPIキー情報の取得
下記の記事の記事の事前準備セクションに「Bot用のアカウント取得方法」及び「APIキー取得方法」について解説してますのでご確認ください。
『News API』APIキー情報の取得
今回、ニュースを取得するAPIとして『News API』を使います。News APIは世界中のさまざまなニュースソースから最新のニュースがリアルタイムで提供されており、キーワード、日付、言語、国に基づいてニュース記事を検索することが可能です。
上記のサイトからアカウント登録するだけで簡単にAPIキーを取得できるのできます。
コード実装〜Webサーバへ公開
保守性と再利用性向上性のため、「APIアクセス層」「ロジック層」「エンドポイント層」を分けて開発します。
「APIアクセス層」・・公開されてるAPIを活用してデータを取得する部分
「ロジック層」・・APIアクセス層から取得したデータを加工する部分
「エンドポイント層」・・ユーザーからのAPIリクエストを受付けて、インプットデータをロジック層へ連携する部分
詳しくは以下の記事を参照してください。
ソースについては量の多さから部分的に公開します。ソースの流れだけ理解していただければ良いかと思います。
APIアクセス層
APIアクセス層は「News API」から提供されるAPIを利用して情報取得します。「News API」のAPIに関するパラメータは以下の通りです。
パラメータ | 説明 |
---|---|
apiKey | アクセスに必要なAPIキー。 |
q | 検索クエリ。記事の中で検索されるキーワードやフレーズ。 |
searchIn | キーワード検索対象のフィールド (title, description, content)。 |
sources | ニュースソースのID。コンマ区切りで複数指定可能。 |
domains | 特定のドメインからの記事を検索。コンマ区切りで複数指定可能。 |
excludeDomains | 検索結果から除外するドメイン。コンマ区切りで複数指定可能。 |
from | 検索対象の開始日。 |
to | 検索対象の終了日。 |
language | 記事の言語。日本語の場合は「ja」。 |
sortBy | 記事のソート順。 |
pageSize | 1ページあたりの記事数。最大100。 |
page | ページ番号。 |
コードは以下の通りです。基本的にAPIパラメータ一覧を基にURLを組み立ててますが、使用しないパラメータは省いています。また、「@handle_request_errors」の部分はAPI接続周りの例外エラー発生時のエラーを分類するためのデコレーター※を付与している。
※デコレーターはPythonにおいて関数やメソッドに新しい機能を動的に追加できます。既存のコードを変更する必要がありません。(チェック処理の追加etcに使えます)
import requests
from utils.api_error_handlers import handle_request_errors
from config import Config
#例外エラー発生時の出力メッセージを定義
@handle_request_errors
def conn_newsapi_evthing(keywords, search_in, sources, language,
sort_by, page, page_size,from_date, to_date):
#URLの組み立て
url = (f”{Config.NEWSAPI_EVTHING_URL}?”
f”q={keywords}&” #AND OR NOT
f”searchIn={search_in}&” #content,title,description
f”sources={sources}&”
f”language={language}&” #jp,en
f”sortBy={sort_by}&”
f”page={page}&”
f”pageSize={page_size}&”
f”from={from_date}&”
f”to={to_date}&”
f”apiKey={Config.NEWSAPI_API_KEY}”)
response = requests.get(url)
return response
ロジック層
ロジック層では「News API」のAPIから取得したニュースのリストから既に削除されてしまっている記事を取り除く作業をします。ブラウザに404エラーを返してくれればよいのですが、ニュースサイト側でエラーハンドリングされてることが大半なのでそれらの記事を除外する必要があったわけです、、(なんかもっと良い方法があれば、、、と思ったのですが。)
from api.newsapi_api import conn_newsapi_evthing
from utils.get_url_content import get_page_content
from config import Config
import json
def get_news_cast(keywords, search_in, sources, language, sort_by, page, page_size, from_date, to_date):
#APIアクセス層からの部品呼び出し
news_data = conn_newsapi_evthing(keywords, search_in,sources,language, sort_by, page, page_size, from_date, to_date)
news_data_json = news_data.json()
articles = news_data_json.get(“articles”, [])
#ファイルが存在しない記事を判断する
valid_articles = filter_valid_articles(articles)
news_data = json.dumps(news_data_json, ensure_ascii=False)
return news_data
#ページが存在しないコンテンツを判断する
def is_page_not_found(content):
#Configファイルから「お探しのページは存在しません」等
のフレーズを読み込む
phrases = Config.CONTENT_NOTFOUND_PHRASES
#記事に取得したフレーズが存在するかを判断する
return any(phrase in content for phrase in phrases)
#ページが存在するコンテンツのみを抽出する
def filter_valid_articles(articles):
valid_articles = []
for article in articles:
url = article[‘url’]
page_content = get_page_content(url)
if page_content and not is_page_not_found(page_content):
#有効な記事のみを追記していく
valid_articles.append(article)
return valid_articles
エンドポイント層
エンドポイント層ではユーザーからの「/news」のURLをトリガーにして「def news():」を動かします。リクエストから取得したパラメータをプログラム内で変数に格納し、ロジック層の部品へ連携します。
from flask import Flask, jsonify, request
from logic.news_cast import get_news_cast
app = Flask(__name__)
# Flaskによるルーティング設定
@app.route(‘/news’, methods=[‘POST’])
# NewsAPIによるニュースの連携
def news():
data = request.get_json()
#リクエストデータの各パラメータを変数に格納する
keywords = data.get(‘keywords’)
search_in = data.get(‘search_in’)
sources = data.get(‘sources’)
language = data.get(‘language’)
sort_by = data.get(‘sort_by’)
page = data.get(‘page’)
page_size = data.get(‘page_size’)
from_date = data.get(‘from_date’)
to_date = data.get(‘to_date’)
#ロジック層のメソッド呼び出し
news = get_news_cast(keywords, search_in, sources, language, sort_by, page, page_size, from_date, to_date)
return news
if name == ‘main’:
app.run(debug=True)
Webサーバへのデプロイ
実装が終わったのでのWebサーバへデプロイします。詳しい方法については以下の記事で丁寧に解説していますので「Webサーバへのデプロイ」の章を参照してください。諸々の設定が終われば「/var/www/app」配下にPythonファイルを配置してApacheのサービス再起動をするだけです。
『Make』シナリオの開発
始めに『Make』の完成図を示します。
大まかな流れを示すと以下のようになります。
① 『HTTP』モジュールを使ってWebサーバへアクセスしてニュース情報を取得
② 取得した情報をリスト化
③ 乱数を使ってリスト化した情報からニュースを選択
④ 選択した情報をXへポスト
各モジュールの設定値について説明します。
『HTTP』モジュール
『Make』から<Make a request>を使ってHTTP経由でWebサーバへアクセスします。
今回はPOST通信でWebサーバへアクセスするので「Request content」に以下のパラメータを設定します。
{
“keywords”: “テクノロジー”,
“search_in”: “title,description”,
“sources”: “”,
“language”: “jp”,
“sort_by”: “publishedAt”,
“page”: 1,
“page_size”: 80,
“from_date”: “{{formatDate(addDays(now; -25); “YYYY-MM-DD”)}}”,
“to_date”: “{{formatDate(now; “YYYY-MM-DD”)}}”
}
『JSON』モジュール
『HTTP』モジュールから返却される値をJSON形式として認識させるために<Parse JSON>モジュールを使用します。
『Array aggregator』モジュール
JSON形式のデータを配列として格納します。
『Math』モジュール
取得したリストからランダムで1つの記事を選びます。『Math』モジュールを使用してリストの長さの範囲から1つの整数を選びます。
『Twitter』モジュール
最後にXへポストして終わりです。
Xのポスト内容を確認してみよう!
ポスト内容はこんな感じです。今回はニュースの「タイトル」と「URL」を出力させてます。工夫すれば色々中たちでのポストが可能となります。
まとめ
今回は「MakeとPythonを使ってXでニュースを自動配信する方法」について解説してきました。1から作ろうとするとかなりの量があったんじゃないかと思います。ただ、使いやすくて人気のある自動化ツール『Make』と個別のロジックを作り上げられるPythonを組み合わせることで最強のオリジナルシステムを作ることが可能になったわけです。今日紹介した内容を基礎に自分なりにアレンジしてみてください。