2017年08月10日

「公式RT直後のツイート」と「コメント付RT」の抜き出しscriptのBootStrap化


車輪の再発明になりますが、Pythonの勉強がてら「公式リツイート直後のツイート...

ただし、見た目がしょぼかったのでBootStrapで下記の様な画面にパワーアップさせました。その時の備忘録です。

20170808_bootstrap_0.jpg
20170808_bootstrap_1.jpg

ちなみにBootstrapとはTwitter社が開発したCSSの「フレームワーク」になります。


BootStrapのダウンロードと展開

CDNをURL指定する方法を実施してみたらうまくいかなかったので、BootStrapを自分のサーバー上に設置して実施する方法を取りました。ダウンロードはこちらからzipで実施しました。

ちなみに展開すると下記の様なディレクトリ構成になります
bootstrap
├─css
│      bootstrap-theme.css
│      bootstrap-theme.css.map
│      bootstrap-theme.min.css
│      bootstrap-theme.min.css.map
│      bootstrap.css
│      bootstrap.css.map
│      bootstrap.min.css
│      bootstrap.min.css.map


├─fonts
│      glyphicons-halflings-regular.eot
│      glyphicons-halflings-regular.svg
│      glyphicons-halflings-regular.ttf
│      glyphicons-halflings-regular.woff
│      glyphicons-halflings-regular.woff2

└─js
        bootstrap.js
        bootstrap.min.js
        npm.js

サーバー上の設置場所

最初CGI直下にBootStrapという名前で設置して失敗したのですが、FlaskでBootStrapを使うためには下記の様に設定するのが正しいようです。

CGI
├─static
│  ├─css
│  ├─fonts
│  └─js
└─templates

タグを打つ……前に入門サイトを参考にする

Googleで調べれば色々出てくるとは思いますが、自分は動画で解説を見ることが出来る下記を参考にしました。このタグを使いたいなーと思ったら動画を止めて打ち込んでいました。


ということで、実際に修正したスクリプトに続きます。

BootStrap用に修正したスクリプト

app.py


#!/usr/local/bin/python3.5

import os
import logging
import tweepy
from flask import Flask, session, redirect, render_template, request

# KEY Information
CONSUMER_KEY="****************************************"
CONSUMER_SECRET="*********************************************"
SECRET_KEY ="********************************************"

CALLBACK_URL = 'http://kumanabe.s1003.xrea.com/cgi/RtKumaFlask/'
#CALLBACK_URL = "http://localhost:5000/"

# Flask の起動
app = Flask(__name__)

# flask の session を使うにはkeyを設定する必要がある.
app.secret_key = SECRET_KEY

@app.route('/')
def index():
""" root ページの表示 """
# Formを表示するかどうか
statusID = request.args.get('statusId')
if statusID:
# StatusIDを取得できていればFormは表示せずに認証に移る(template/index.html)
# StatusIDは後で使うので保存
formOn = 0
session['stausID'] = statusID
else:
# StatusIDを取得できていればFormを表示する(template/index.html)
formOn = 1

# ReTweet情報の取得
tweetListRT = user_rtinfo()
# templates/index.html を使ってレンダリング.
return render_template('index.html', tweetListRT=tweetListRT, formOn=formOn)

@app.route('/twitter_auth', methods=['GET'])
def twitter_auth():
""" 連携アプリ認証用URLにリダイレクト """
# tweepy でアプリのOAuth認証を行う
try:
auth = tweepy.OAuthHandler(CONSUMER_KEY, CONSUMER_SECRET,CALLBACK_URL)
redirect_url = auth.get_authorization_url()
# 認証後に必要な request_token を session に保存
session['request_token'] = auth.request_token
except:
logging.error("Auth Error")

return redirect(redirect_url)

def user_rtinfo():
""" user の timeline のリストを取得 """
# request_token と oauth_verifier のチェック
token = session.pop('request_token', None)
verifier = request.args.get('oauth_verifier')
if token is None or verifier is None:
return False # 未認証ならFalseを返す

# tweepy でアプリのOAuth認証を行う
auth = tweepy.OAuthHandler(CONSUMER_KEY, CONSUMER_SECRET, CALLBACK_URL)

# Access token, Access token secret を取得.
auth.request_token = token
try:
auth.get_access_token(verifier)
except tweepy.TweepError:
return {}

# tweepy で Twitter API にアクセス
api = tweepy.API(auth)

# 検索したいstatusIDをsessionから取得
statusId = session.pop('stausID',None)
# RTから7日以内のTweetを取得する方針
RTDate = 7
try:
retweeters = api.retweets(id=statusId) #rtした人一覧
except:
print ("Auth or api error. Would you please move to prev page?</br>")
return ""

# RTに関係したTweetをリストで保存する
tweetListRT = []
tweetListQT = []
#                            秒  分  時間  日
statusIdAfterxDays = int(statusId) + 2**22 * 1000 * 60 * 60 * 24 * RTDate
for retweeter in retweeters:
postlineon = 0;
postline ="";

for tweet in tweepy.Cursor(api.user_timeline, id = retweeter.user.id, since_id = str(int(statusId)-1), max_id = statusIdAfterxDays, cursor = -1).items():
if hasattr(tweet,"retweeted_status"):
if str(tweet.retweeted_status.id) == str(statusId):
if(postlineon == 1):
# ひとつ後のTweetがあればリストに放り込む
tweetListRT.append(["R",postTweet])

# RT自身をリストに保存
tweetListRT.append(["RO",tweet])
break

# 新しい方から順次Tweetを1つ分だけ保存しておく
postlineon = 1;
postTweet = tweet;

# ここから先はコメント付Retweet関連
maxId = statusIdAfterxDays # 検索結果用ID
maxIdOld = statusIdAfterxDays # 検索結果用ID

# コメント付Rtはコメント先のRTのリンクで検索するので、検索用のURLを作成して検索
statusTweet = api.get_status(statusId)
userId = statusTweet.user.screen_name
searchWord = "https://twitter.com/" + userId + "/status/" + statusId
for tweet in tweepy.Cursor(api.search, q=searchWord,since_id = str(int(statusId)-1),max_id=maxId, cursor = -1).items():
tweetListRT.append(["Q",tweet])

return tweetListRT

if __name__ == '__main__':
app.run(debug=True)

template/index.html

 <!DOCTYPE html>
<script>window.twttr = (function(d, s, id) {
var js, fjs = d.getElementsByTagName(s)[0],
t = window.twttr || {};
if (d.getElementById(id)) return t;
js = d.createElement(s);
js.id = id;
js.src = "https://platform.twitter.com/widgets.js";
fjs.parentNode.insertBefore(js, fjs);

t._e = [];
t.ready = function(f) {
t._e.push(f);
};
return t;
}(document, "script", "twitter-wjs"));</script>

<html lang="ja">
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>KumaKuma Web Site</title>
<link href="static/css/bootstrap.min.css" rel="stylesheet">
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.3/jquery.min.js"></script>
<script src="static/js/bootstrap.min.js"></script>
</head>

<body>
<nav class="navbar navbar-default navbar-fixed-top">
<div class="navbar-header">
<a class="navbar-brand" href="http://kumanabe.s1003.xrea.com/cgi/RtKumaFlask/">KumaKuma RT Checker [ツイートのStatusIDを入力 ⇒「公式RT直後のツイート」と「コメント付RT」を表示]</a>
</div>
</nav>

{% if tweetListRT == False %}
{% if formOn == 1 %}
<div class ="container" style="padding:60px 0 0 0">
<form class="form-inline">
<div class="form-group">
<label class="control-label" for="Tweet StatusId">Tweet Status ID</label>
<input type="text" class="form-control" id="statusId" name="statusId" placeholder="01234567890123456">
</div>
<button type="submit" class="btn btn-primary">Checking Tweets after RT</button>
</form>
</div>
{% else %}
<p>連携アプリ認証をします。自動的に遷移しない場合は<a href="{{ url_for('twitter_auth') }}">クリック</a></p>
<meta http-equiv="refresh" content="1;URL={{ url_for('twitter_auth') }}">
{% endif %}
{% elif tweetListRT == "" %}
Retweet wasn't found</br>
{% else %}
<div class ="container" style="padding:60px 0 0 0">

<!--タブ部分のソース-->
<ul class="nav nav-tabs">
<li class="active"><a href="#tab1" data-toggle="tab">公式RT</a></li>
<li><a href="#tab2" data-toggle="tab">コメント付RT</a></l0i>
</ul>
<!-- / タブ部分のソース-->

<div id="myTabContent" class="tab-content">
<div class="tab-pane fade in active" id="tab1">
{% for tweet in tweetListRT %}
{% if tweet[0] == "R" or tweet[0] == "RO"%}
{% if tweet[0] == "RO" %}
<div style="padding:0px 0px 0px 70px">
{% endif %}
<blockquote class="twitter-tweet" data-lang="ja">
<p lang="ja" dir="ltr"> {{ tweet[1].text }} </p> &mdash;
{{ tweet[1].user.screen_name }}/{{ tweet[1].user.name }}
<a href="https://twitter.com/{{ tweet[1].user.screen_name }}/status/{{ tweet[1].id_str }}">
{{ tweet[1].created_at }}</a>
</blockquote>
{% if tweet[0] == "RO" %}
</div>
{% endif %}
<script async src="//platform.twitter.com/widgets.js" charset="utf-8"></script>
{% endif %}
{% endfor %}
</div>

<div class="tab-pane fade" id="tab2">
{% for tweet in tweetListRT %}
{% if tweet[0] == "Q" %}
<blockquote class="twitter-tweet" data-lang="ja">
<p lang="ja" dir="ltr"> {{ tweet[1].text }} </p> &mdash;
{{ tweet[1].user.screen_name }}/{{ tweet[1].user.name }}
<a href="https://twitter.com/{{ tweet[1].user.screen_name }}/status/{{ tweet[1].id_str }}">
{{ tweet[1].created_at }}</a>
</blockquote>
<script async src="//platform.twitter.com/widgets.js" charset="utf-8"></script>
{% endif %}
{% endfor %}
</div>
</div>
</div>
{% endif %}

<footer>
</footer>
</body>
</html>

スポンサーリンク
posted by くまなべ at 06:38 | Comment(0) | TrackBack(0) | Python
この記事へのコメント
コメントを書く
お名前:

メールアドレス:

ホームページアドレス:

コメント:

この記事へのトラックバックURL
http://blog.sakura.ne.jp/tb/180578157
※ブログオーナーが承認したトラックバックのみ表示されます。

この記事へのトラックバック