djangoでツイートを検索して結果を表示してみた

2022年5月3日

djangoでツイート検索をしてみた

前回の記事「twitterAPIとpythonを使ってツイートの埋め込みコードを取得してみる」では特定のキーワードでツイートを検索しました。
今回はdjangoと組み合わせた「キーワードの検索ボックス」を設置して「ツイート」をブラウザ上に表示してみたいと思います。APIの記事はほぼ前回の記事と一緒です。動きは下の通りです。

views.py

今回「oauth_session」のパラメータは「ログインユーザー」によって使い分けたかったのでapiではなくviewsに記載するようにしました。
※securit...の部分は今回の機能には直接関係ないので実装する場合は消してください。


from django.shortcuts import render
from django.shortcuts import redirect
#--独自モジュール--------------------------------------
from twitter.modules import security
from twitter.modules import api
#--メッセージ------------------------------------------
from django.contrib import messages
#--ログツール------------------------------------------
import logging
#logging.debug('hi_debug')
def search_tweets(request):
    if request.method == 'POST':
        keyword = request.POST['keyword']
        count   = request.POST['count']
        if security.exist_submit_token(request) and keyword and count:
            #ログインユーザーによって取得する値を変更する為、後日下記情報DBから取得出来るように変更
            oauth_session_params = {}
            oauth_session_params['consumer_key']    = 'xxxxxxxxxx'
            oauth_session_params['consumer_secret'] = 'xxxxxxxxxx'
            oauth_session_params['access_token']    = 'xxxxxxxxxx'
            oauth_session_params['access_secret']   = 'xxxxxxxxxx'
            #--------------------------------------
            twitterApi = api.TwitterApi(oauth_session_params)
            tweets = twitterApi.get_tweets(keyword, count)
        else:
            return redirect('twitter:search_tweets')
    else:
        keyword = ''
        count   = 5
        tweets  = ''
    submit_token = security.set_submit_token(request)
    context = {
        'keyword': keyword,
        'count'  : count,
        'tweets' : tweets,
        'submit_token': submit_token,
    }
    return render(request, 'twitter/search_tweets.html', context)

api.py

twitterApiインスタンスは純粋にviews.pyから受け取った「oauth_sessionの情報」「検索ワード」「検索件数」を受け取り結果を返すようにしております。


#--twitter読み込み-------------------------------------
import json
from requests_oauthlib import OAuth1Session
#--ログツール------------------------------------------
import logging
#logging.debug('hi_debug')
class TwitterApi:
    def __init__(self, oauth_session_params):
        CONSUMER_KEY    = oauth_session_params['consumer_key']
        CONSUMER_SECRET = oauth_session_params['consumer_secret']
        ACCESS_TOKEN    = oauth_session_params['access_token']
        ACCESS_SECRET   = oauth_session_params['access_secret']
        self.twitter    = OAuth1Session(CONSUMER_KEY, CONSUMER_SECRET, ACCESS_TOKEN, ACCESS_SECRET)
        self.url_trend  = "https://api.twitter.com/1.1/trends/place.json"
        self.url_search = "https://api.twitter.com/1.1/search/tweets.json"
        self.url_embed  = "https://publish.twitter.com/oembed"
        self.url_status = "https://api.twitter.com/1.1/statuses/show.json"
    def search_tweets(self, keyword, count):
        params = {'q': keyword, 'count': count}
        request = self.twitter.get(self.url_search, params = params)
        if request.status_code == 200:
            search_tweets = json.loads(request.text)
            return search_tweets
    def get_tweet_ids(self, search_tweets):
        tweet_ids = []
        for tweet in search_tweets['statuses']:
            tweet_ids.append(str(tweet['id']))
        return tweet_ids
    def get_screen_names(self, tweet_ids):
        embed_params_dicts = []
        for tweet_id in tweet_ids:
            params = {'id': tweet_id}
            request = self.twitter.get(self.url_status, params = params)
            status = json.loads(request.text)
            screen_name = status['user']['screen_name']
            embed_params_dict = {}
            embed_params_dict['tweet_id'] = tweet_id
            embed_params_dict['screen_name'] = screen_name
            embed_params_dicts.append(embed_params_dict)
        return embed_params_dicts
    def get_embed_datas(self, embed_params_dicts):
        embed_datas = []
        for e in embed_params_dicts:
            url = 'https://twitter.com/'+e['screen_name']+'/'+'status/'+e['tweet_id']
            params = {'url': url, 'hide_media': False, 'align': 'center'}
            request = self.twitter.get(self.url_embed, params = params)
            embed_data = json.loads(request.text)
            embed_datas.append(embed_data['html'])
        return embed_datas
    def get_tweets(self, keyword, count):
        search_tweets      = self.search_tweets(keyword, count)
        tweet_ids          = self.get_tweet_ids(search_tweets)
        embed_params_dicts = self.get_screen_names(tweet_ids)
        embed_datas        = self.get_embed_datas(embed_params_dicts)
        return embed_datas

search_tweets.html

テンプレートは何てことありませんが「{{ tweet | safe }}」だけがポイントですね。
受け取った埋め込みデータは「safe」を付けてあげないとHTMLがそのまま表示されてしまします。
参考:DjangoでマークダウンをHTMLに変換するためにHTMLを生で出力する方法


{% extends 'account/base.html' %}
{% block content %}
{% load widget_tweaks %}
<div class="search-container">
    <form action="." method="post" class="">{% csrf_token %}
        <input type='text' id="keyword" name="keyword" value="{{keyword}}" placeholder="keyword" class="search-box">
        <input type='text' id="keyword" name="count" value="{{count}}" placeholder="count" class="search-box">
        <input type="hidden" name="submit_token" value="{{ submit_token }}" class="input_box">
        <input type="submit" value="search" class="search-button">
    </form>
</div>
{% for tweet in tweets %}
    {{ tweet | safe }}
{% endfor %}
{% endblock %}

2022年5月3日