☆☆ 新着記事 ☆☆

2019年5月28日火曜日

Python Google Translatorを使ってみた


1. pipでインストール

(venv) C:\Users\User名\Desktop\top>pip install googletrans
Collecting googletrans

2.使う

from googletrans import Translator
text='Hello, world!'
translator = Translator()

ja = Translator().translate(text, src='en', dest='ja')

>>> print(ja)
Translated(src=en, dest=ja, text=こんにちは世界!, pronunciation=None, extra_data="{'translat..
.")
>>> print(ja.text)
こんにちは世界!

--->
ja.textとしてTextデータだけを格納しないと、text/string 属性のデータベースには格納できない。
エラーになる。


(Memo: )
for i in tweets:
     print(i.created_at)
     print(i.id)
     print(i.full_text)
     ja_pre =strip_emoji(i.full_text)
     ja_google_obj = Translator().translate(ja_pre , src='en', dest='ja')
     print(ja_google_obj)
     print("==================================")

#Output
==================================
2019-07-26 22:37:00
1154883345546928128
Wow! Big VICTORY on the Wall. The United States Supreme Court overturns lower court injunction, allows Southern Border W
all to proceed. Big WIN for Border Security and the Rule of Law!
Translated(src=en, dest=ja, text=うわー!壁に大きな勝利。米国最高裁判所は、下級裁判所の差し止め命令を覆し、Southern Bord
er Wallが続行することを許可します。国境警備と法の支配に大勝利!, pronunciation=None, extra_data="{'translat...")
==================================
2019-07-26 22:18:26
1154878670739300358
https://t.co/nr9bDv3Ktq
Translated(src=en, dest=ja, text=https://t.co/nr9bDv3Ktq, pronunciation=None, extra_data="{'translat...")
==================================


☆これで動くので忘れないようにメモ

import tweepy as tw         
import pandas as pd   
from credentials import *
import pytz
import datetime
from googletrans import Translator
import json
import pprint

   
def twitter_setup():
    auth = tw.OAuthHandler(CONSUMER_KEY, CONSUMER_SECRET)
    auth.set_access_token(ACCESS_TOKEN, ACCESS_SECRET)
    api = tw.API(auth,wait_on_rate_limit=True)
    return api
extractor = twitter_setup()

def index():
     # Retrieve Tweets
     tweets = extractor.user_timeline(screen_name="realDonaldTrump",
                                      count=3,include_rts=True,tweet_mode="extended")
     tweet = tweets[0]
     b=tweet._json
     c = b["full_text"]
     print("C is \t")
     print(c)
     ja = Translator().translate(c, src='en', dest='ja')
     print(ja)
     tweet = tweets[1]
     aa=tweet._json
     bb =aa["full_text"]
     print("bb is \t")
     print(bb)
     ja2 = Translator().translate(bb, src='en', dest='ja')
     print(ja2)
     i=0
     for i in range(len(tweets)):
         tweet = tweets[i]
         aa=tweet._json
         bb =aa["full_text"]
         print("bb loop is \t")
         print(bb)
         ja2 = Translator().translate(bb, src='en', dest='ja')
         print(ja2)
         i += 1
    

     #print(text_ja)
   
         

index()


◇Emojiとか入ってるとエラーになるのを取り除く。
https://gist.github.com/Alex-Just/e86110836f3f93fe7932290526529cd1

RE_EMOJI = re.compile('[\U00010000-\U0010ffff]', flags=re.UNICODE)

def strip_emoji(text):
    return RE_EMOJI.sub(r'', text)
print(strip_emoji('🙄🤔'))




☆Twitterのテキストを翻訳する場合
上記のままだと、以下のエラーコード。
json.decoder.JSONDecodeError: Expecting value: line 1 column 1 (char 0)

参考)
あまり見てないけど、丁寧そう。
https://www.codeproject.com/Tips/1236705/How-to-Use-Google-Translator-in-Python


☆ ある日突然、つかえないことに、、、、

 今までつかえていたのに、
 
  File "/home/tw_virtualenv/lib/python3.7/site-packages/googletrans/client.py", line 172, in translate
    data = self._translate(text, dest, src)
  json.decoder.JSONDecodeError: Expecting value: line 1 column 1 (char 0)

 などと、エラーが。。。

 他のサーバーではできる。

 なんと
 Googletrans: Free and Unlimited Google translate API for Python

 と書いているのに、Google自身がBanしてくることがあるらしい。


>>> from googletrans.gtoken import TokenAcquirer
>>> acquirer = TokenAcquirer()
>>> text = 'test'
>>> tk = acquirer.do(text)
>>> tk
'222835.391456'

というTokenを使って管理しているらしい。 このTokenを
googletrans stopped working with error 'NoneType' object has no attribute 'group'
https://stackoverflow.com/questions/52455774/googletrans-stopped-working-with-error-nonetype-object-has-no-attribute-group

で、リセットするようにするらしいが、どうもイタチごっこで、上手く行くときも、いかないときもあるよう

24時間、待つと良くなることもあるようなので待ってみる。

こんな時でも、別サーバーは動く。
>>> from googletrans import Translator
>>> text = "Hello World!"
>>> print(text)
Hello World!
>>> translator=Translator()
>>> ja=Translator().translate(text,src='en',dest='ja')
>>> print(ja)
Translated(src=en, dest=ja, text="こんにちは世界", pronunciation=None, extra_data="{'translat...")

2019年5月27日月曜日

CRONでVirtualenvを立ち上げて、pythonアプリを定期的に実行する: CentOS 7


CRONを触るのが初めてですが、CentOSでcronで、指定した時間に

1) Virtualenvを立ち上げ、
2) pythonアプリを動かす

ことが、以下の設定で出来ました。 


cronで仮想環境を立ち上げてから、アプリを起動する

情報があまりなく、苦労したので、備忘として、まとめておきます。

良く参照する時間の設定だけ、ここに再掲。
crontab -u root -e
cronの設定を記述
分 時 日 月 曜日 <実行コマンド>

・固定指定
以下のように設定すると、15時になる度に実行。
0 15 * * * echo "hello."

・間隔指定
間隔を指定したい場合。
例では、5分毎に実行されます。

*/5 * * * * echo "hello."

・複数指定
複数時間を設定したい場合はカンマ(,)で区切ります。
例では、午前2時5分と午前2時10分に実行。

5,10 2 * * * echo "hello."

・範囲指定
複数指定よりも範囲で指定した方がいい場合があります。
 以下のようにすると、指定範囲で実行できます。
 例では、午前2時5分、午前3時5分、午前4時5分、午前5時5分に実行されます。

5 2-5 * * * echo "hello."
月曜-金曜
0 15 * * mon-fri echo "hello."



*****結論だけ知りたい方*****

crontabに以下の書式で記述することでアプリを実行できます。


◇毎日 13:00pm (JST)に実行。

* 13 * * * cd  [ 実行するpython executableのディレクトリまでのフルパス] &&
 [ 仮想環境のpythonまでのフルパス] [実行したいパイソンファイル名]  config/config.ini > /dev/null 2>&1

で、実現できます。 例えば、具体的には以下のような記述。

* 13 * * * cd  /var/www/html/app &&  /home/virtualenv/bin/python test.py  config/config.ini > /dev/null 2>&1

1) /var/www/html/app
このディレクトリに、実行したいpythonのアプリファイルを格納しています。

2)  /home/virtualenv/bin/python
使用したい仮想環境のpythonまでのフルパス

3) test.py
1)のディレクトリに格納している、実行するpyファイルです。



これでcronでVirtualenvを立ち上げて、Pythonを実行できるね。

参考)仮想環境を立ち上げる必要がない場合は、

* 13 * * * python3 /var/www/html/app/ test.py

という、分かり易い書き方になります。




*****以下、基本事項を確認しなら*****

cronの設定 手順

0. crondの状態確認

1)crond が動いているかどうか

systemctl status crond.service
● crond.service - Command Scheduler
   Loaded: loaded (/usr/lib/systemd/system/crond.service; enabled; vendor preset: enabled)
   Active: active (running) since Sat 2019-05-04 12:17:34 JST; 3 weeks 1 days ago  Main

PID: 13525 (crond)

2) crond 動いていなかったらOS起動時に Cron も自動起動するようにしておきす。
# systemctl enable crond.service (systemctl start crond)
#systemctl start crond.service (systemctl start crond)

2) crond ログの確認
tail -f /var/log/cron

1. CentOS 7 用の設定

CentOS7では初期設定でcronie-anacronがインストールされており、ジョブの実行時間に幅を持たせている。 指定日時ぴったりにジョブを実行したい場合、cronie-noanacronを入れる必要がある。
依存関係上先に、cronie-noanacronをインストールし、その後にcronie-anacronを削除する。

(確認)
[root@ueczshc7 ~]# yum list installed | grep cronie
cronie.x86_64                          1.4.11-17.el7              @base/7.4.1708
cronie-anacron.x86_64                  1.4.11-17.el7              @base/7.4.1708


# yum -y install cronie-noanacron
Installed:
  cronie-noanacron.x86_64 0:1.4.11-20.el7_6 Dependency Updated:
  cronie.x86_64 0:1.4.11-20.el7_6    cronie-anacron.x86_64 0:1.4.11-20.el7_6
Complete!

# yum -y remove cronie-anacron
Removed:
  cronie-anacron.x86_64 0:1.4.11-20.el7_6 Complete!

[root@ueczshc7 ~]# yum list installed | grep cronie
cronie.x86_64                          1.4.11-20.el7_6            @updates
cronie-noanacron.x86_64                1.4.11-20.el7_6            @updates


設定は/etc/cron.d/dailyjobsで行う。設定の確認。

$ cat /etc/cron.d/dailyjobs
[root@eowrirn3 ~]# cat /etc/cron.d/dailyjobs


# Run the daily, weekly, and monthly jobs if cronie-anacron is not installed

SHELL=/bin/bash PATH=/sbin:/bin:/usr/sbin:/usr/bin
MAILTO=root
# run-parts
02 4 * * * root [ ! -f /etc/cron.hourly/0anacron ] && run-parts /etc/cron.daily
22 4 * * 0 root [ ! -f /etc/cron.hourly/0anacron ] && run-parts /etc/cron.weekly
42 4 1 * * root [ ! -f /etc/cron.hourly/0anacron ] && run-parts /etc/cron.monthly

cronie-anacronが削除されない場合は、実行されないようになっていることが分かる。


実行したいシェルは頻度に応じて/etc/cron.daily、/etc/cron.weekly、/etc/cron.monthlyに配置する。配置後にcrondの再起動が必要。

$ sudo systemctl restart crond

ログは/var/log/cronに出力される
ログの確認。

$ sudo less /var/log/cron

(以上、https://qiita.com/satouf/items/38a4e01e5ac493a67eb2


****cronのログをvi で編集すると、ログが更新されなくなることがある。
そんな時は、
service rsyslog restart
を実行。


2. crontabの設定

1)参照
# crontab -l
10 * * * * /root/crontest.sh

2)編集
crontab -u root -e

3)記述方法
cronの設定を記述
分 時 日 月 曜日 <実行コマンド>

・固定指定
以下のように設定すると、15時になる度に実行。
0 15 * * * echo "hello."

・間隔指定
間隔を指定したい場合。
例では、5分毎に実行されます。

*/5 * * * * echo "hello."

・複数指定
複数時間を設定したい場合はカンマ(,)で区切ります。
例では、午前2時5分と午前2時10分に実行。

5,10 2 * * * echo "hello."

・範囲指定
複数指定よりも範囲で指定した方がいい場合があります。
 以下のようにすると、指定範囲で実行できます。
 例では、午前2時5分、午前3時5分、午前4時5分、午前5時5分に実行されます。

5 2-5 * * * echo "hello."

上記の書式で記述後、保存してエディタを閉じると設定完了です。

設定読み込み作業は不要で、保存すると自動で実行されるが、、

#設定ファイルの読み込み
#cronの設定を記述したファイルを読み込むことで、cronを設定できます。
#echo '*/5 * * * * echo "hello."' > cron.conf crontab cron.conf

crontabで、-rオプションを誤ってつけてしまうと、設定が全て消去されてしまいます。



3.仮想環境を起動して、Python実行

(手順)

* * * * * /usr/bin/env bash -c 'YOUR_COMMAND_HERE' > /dev/null 2>&1


◇記述例1 (bashでVirtualenvを起動させる方法)
0 3 * * * /usr/bin/env bash -c 'cd /var/www/html/app/ && source /home/virtualenv/bin/activate && ./test.py command arg' > /dev/null 2>&1


◇記述例2 (仮想環境下のPythonをポイントする方法)
0,30 * * * * cd /home/myuser/myproject && venv/bin/python bot.py config/config.ini > /dev/null 2>&1

◇適用例2

* * * * * cd  /var/www/html/app/ &&  /home/virtualenv/bin/python test.py  config/config.ini > /dev/null 2>&1

記述例3 (python app内に、仮想環境を起動するscriptを書き込む)

# coding: utf-8
activate_this ='/home/virtualenv/bin/activate_this.py'
exec(open(activate_this).read(), {'__file__': activate_this}) import sys sys.path.insert(0, '/var/www/html/app')

*****************************************

2019年5月26日日曜日

Jinja2 に 2つのリストをzipして渡す

(app.py)

  return render_template("trump_list.html", data=zip(list1,list2))

(Jinja2)

     {% for text, ET in data%}
     <div class="content-section">
     {{text | safe}}
     {{ET}} in ET <h6>(New York/Washington D.C Time)</h6>
     </div>
     {% endfor %}

*Zip関数の一般的な書き方

names = ['Alice', 'Bob', 'Charlie']
ages = [24, 50, 18]
points = [100, 85, 90]

for name, age, point in zip(names, ages, points):
    print(name, age, point)

2019年5月23日木曜日

Pandas DataFrameのサンプル作成と基本操作

Pandasフレーム・ワークを作って操作してみるのに、毎回、考えてサンプルを作るのは面倒なので、コピペできるようにメモしておきます。

Colomunsの追加、削除、値の検索などのテスト用に使ってください。
(元になるリストは日付データにしていて、タイムゾーンの変更もしてますが、参考まで。)


import datetime
import pytz
import pandas as pd
import numpy as np
import random

string_date='2019/05/19 04:00:00'
dt = datetime.datetime.strptime(string_date,'%Y/%m/%d %H:%M:%S')
dt_utc=dt.replace(tzinfo=pytz.UTC)

#元ネタのリスト用意
list1=[]
for  i in range(10):
    list1.append(dt_utc + datetime.timedelta(hours=-i))

list2 = [random.randint(200,299) for i in range(10)]
print(list1,list2)

#(参考)辞書の作り方
myDict = dict(zip(list1,list2))
print(myDict)



#pandasデータフレームワーク作成
date_pd = pd.DataFrame(data = [ [list1[i]] for i in range(len(list1))], columns=['Date'])
print(date_pd)

 #pandasデータフレームワークのコラム追加
date_pd['Text']=([list2[i] for i in range(len(list2))])
print(date_pd)

 #pandasデータフレームワークのコラムの確認
print(date_pd.columns)

 #検索条件の作成
string_date='2019/05/19 04:00:00'
dt = datetime.datetime.strptime(string_date,'%Y/%m/%d %H:%M:%S')
dt_utc=dt.replace(tzinfo=pytz.UTC)

dt_start=list1[6]
print(dt_start)

dt_end=list1[3]
print(dt_end)

 #リストの範囲を指定してcolumnsを追加
for i in range(len(date_pd)):
     if date_pd.at[i,"Date"] < dt_end and date_pd.at[i,"Date"]> dt_start:
          date_pd.at[i,'Check']=np.array('Checked')
print(date_pd)

 #データフレームワークの範囲を指定して新しいデータフレームワーク作成
## df[df.A > 0] #これだと、全ての行を検索しTrue/Falseを返す。If文との併用が必要。
[10 rows x 3 columns]                                                 
 print(date_pd.Date>dt_end)
 #0     True                                                            
 #1     True                                                            
 #2     True                                                            
 #3    False                                                            
 #4    False                                                            
 #****continue
 #9    False  

date_pd_selected=date_pd[date_pd.Date>dt_end]   #新しいデータフレームワーク作成可能
print(date_pd_selected)
                       Date  Text Check                              
 0  2019-05-19 04:00:00+00:00   298   NaN                              
 1  2019-05-19 03:00:00+00:00   247   NaN                              
 2  2019-05-19 02:00:00+00:00   201   NaN           

 FutureWarning:converting timezone-aware DatetimeArray to timezone-naive ndarray with 'datetime64[ns]' dtype. In the future, this will return an ndarray with 'object' dtype where each element is a 'pandas.Timestamp' with the correct 'tz'.
        To accept the future behavior, pass 'dtype=object'.
        To keep the old behavior, pass 'dtype="datetime64[ns]"'.
  result = np.asarray(values, dtype=dtype)   

2019年 新卒 データ・サイエンティストの初任給が1000万円越え -



残念ながら日本の話ではありません。 これは、米国の2019年新卒社員の給与(正確にはEntry Level Job : 入社 1~3年目程度)の給与について、口コミ企業情報のGlassdoor社の調査を受けて、米Bloomberg社が記事にしたものです。

この調査は、IT業界で働く社員だけを対象に調査したものではありません。

全業種を調査した結果、TOP 10 がこちら。


These Are the Highest Paying Jobs for the Class of 2019

No 1. Data Scientist                  USD 95,000-
No 2.Software Engineer                USD 90,000-
No 3.Product Manager           USD 89,000 -
No 4.Product Designer          USD 85,000-
No 5.Investment Banking Analyst  USD 85,000-
No 6.UX Designer                             USD 73,000-
No 7.Java Developer                         USD 72,000 -
No 8.Implementation Consultant    USD 72,000-
No 9.Systems Engineer                     USD 70,000-
No 10.Software Developer                USD 68,000-


この記事の中でも指摘されていますが、データ・サイエンティストがWall Streetの花形であるInvestment Bankの社員を抑えて、第一位になりました。

そして、この一覧をみて気が付くことは、圧倒的にIT関連の職種の給与が高い、という事です。
アメリカは、戦略が決まると一気に投資をするため(この場合は人材投資)、人気の職種は急激に給与が高騰することが良くあります。

さて、日本でもIT系の社員の給与は上がり始めていますが、まだまだ、商社社員や銀行員、報道関係の給与が高いようです。

アメリカの現象が数年遅れて入ってくる日本ですが、IT系エンジニアの給与が、やはり一番高くなるような時代が来るのでしょうか?

もっと、詳しく知りたい方は、こちらに解説記事がのっています。
(英語ですが、どうぞ)
https://www.bloomberg.com/news/articles/2019-05-15/big-data-skills-earn-high-pay-for-today-s-college-graduates

2019年5月21日火曜日

PythonのDateTime.Object(UTC) のタイムゾーン変更 - 実践編

import datetime
import pytz
import pandas as pd
import numpy as np

string_date='2019/05/19 04:00:00' #文字列

#文字列を日付情報に
dt_end = datetime.datetime.strptime(string_date,'%Y/%m/%d %H:%M:%S')
print(dt_end )       # output:2019-05-19 04:00:00
print(type(dt_end)) # output:<class 'datetime.datetime'>


#生成済みの日付オブジェクトに、タイムゾーン情報を付与
new_date=dt_end.replace(tzinfo=pytz.UTC)
print(new_date)# output:2019-05-19 04:00:00+00:00


#UTCタイムゾーンを、ETタイムゾーンに
et = pytz.timezone('US/Eastern')
dt_et = new_date.astimezone(et)
print(dt_et)# output:2019-05-19 00:00:00-04:00 


#UTC時間のdt_endから24時間前の時間を取得しリスト化
dt_start = dt_end + datetime.timedelta(days=-1)

time_list=[]
for  i in range(len(time_pd)):
    time_list.append(dt_end + datetime.timedelta(hours=-i))
time_pd = pd.DataFrame(data = [[time_list[i]]for i in range(len(time_pd))], columns=['Date'])
print(time_pd)

print(time_pd.at[0,'Date'])#要素へのアクセス
for i in range(len(time_pd)):
    if time_pd.at[i,"Date"] < dt_end and time_pd.at[i,"Date"]> dt_start:
         time_pd.at[i,'Text']=np.array('Checked')
print(time_pd)

◇datetimeモジュールと利用可能なクラス

https://docs.python.org/3/library/datetime.html

datetimeモジュールには、3つのクラスが用意されている。
クラス             用途
date      主に日付を表現
time      時刻を表現
datetime  日付と時刻を合わせて表現

*datetime.date : 日付
today= datetime.date.today()   #dateクラスにはtodayというattributeはない。
print(today) #2019-05-26

*注意)
date objectと datetime objectの比較はできない。


*datetime.time : 時刻
time_test = datetime.time(13, 32, 30, 1234)
print(time_test) #13:32:30.001234
のようにして使う。このクラスには、now()のようなモジュールがなく、現在時刻を取得するというような便利なことはできない。

*datetime.datetime : 日時(日付と時刻)
(import datetime の後、from datetime import datetimeまで記述しておけば、 datetime.datetimeと2度記述せずに、datetime.now()などと記述できる。)

now= datetime.datetime.now()
print(now) #2019-05-26 00:02:27.209096
print(now.tzinfo)  # timezone情報の確認
>> None


#直接utcの時刻を取得
utc=pytz.timezone('UTC')
now_utc = datetime.datetime.now(utc)
print(now_utc) #2019-05-25 16:40:09.428642+00:00

hour_now = now_utc.hour ♯ Int型
print(hour_now) #16

minute_now = now_utc.minute ♯ Int型
print(minute_now) #40

time_now = hour_now + minute_now ♯これはやってはいけない例
print(time_now) #56

time_now2 = now_utc.time() ♯ 時刻だけ取得したい場合はこれ。(1)
print(time_now2) ♯17:24:49.205886

dt = datetime.datetime.now() ♯ 時刻だけ取得したい場合はこれ。(2)
d_truncated = datetime.date(dt.year, dt.month, dt.day)
print(d_truncated) #2019-05-26

*文字列の表示形式を変更

  date = '2019-07-16 02:11:46'
  #String to Date Object
  dte = datetime.datetime.strptime(date, '%Y-%m-%d %H:%M:%S')
 
  #Date Object to String with format change
  dt_truncated = datetime.date(dte.year, dte.month, dte.day)
  print(dt_truncated) #2019-07-16


◇timeモジュール
time()関数を使うと現在のUNIX時間(エポック秒)を浮動小数点数float型で取得できる。
import time
time = time.time()
print(time) #1558801964.0242553


*datetime.timedelta : 時間差・経過時間
 (datetime.datetime.timedelta ではない。

*strftime(): 日付、時間から文字列への変換
*strptime(): 文字列から日付、時間への変換

*日付フォーマットの変更
today1= datetime.date.today()
today2= "{0:%Y/%m/%d}".format(today1)

*日付自身の変更
new_date=dt_end.replace(hour=4, minute=0, second=0, microsecond=0)


使用できる書式化コード
*%d : 0埋めした10進数で表記した月中の日にち
*%m : 0埋めした10進数で表記した月
*%y : 0埋めした10進数で表記した西暦の下2桁
*%Y : 0埋めした10進数で表記した西暦4桁
*%H : 0埋めした10進数で表記した時 (24時間表記)
*%I : 0埋めした10進数で表記した時 (12時間表記)
*%M : 0埋めした10進数で表記した分
*%S : 0埋めした10進数で表記した秒
*%f : 0埋めした10進数で表記したマイクロ秒(6桁)
*%A : ロケールの曜日名
*%a : ロケールの曜日名(短縮形)
*%B : ロケールの月名
*%b : ロケールの月名(短縮形)
*%j : 0埋めした10進数で表記した年中の日にち(正月が'001')
*%U : 0埋めした10進数で表記した年中の週番号 (週の始まりは日曜日)
*%W : 0埋めした10進数で表記した年中の週番号 (週の始まりは月曜日)

jst=pytz.timezone('Asia/Tokyo')
utc=pytz.timezone('UTC')
et=pytz.timezone('US/Eastern')
#error: astimezone() cannot be applied to a naive datetime

2019年5月19日日曜日

PythonのDateTime.Object(UTC) のタイムゾーン変更

Python の DateTime Objectは、timedelitaを使って簡単に必要な変更ができる。

タイムゾーンの情報を持った日付情報を 'aware' と言い、そうでないものを'naive' という。

classmethod datetime.now(tz=None)

(使い方)
import datetime

now = datetime.datetime.now(tz=None)
print(now) #2019-05-25 20:55:32.227350


◇基本の修正
import datetime

now = datetime.datetime.now()
est_time = tweet.created_at + datetime.timedelta(hours = -5)

hoursは、修正する対象の単位で、他にも、weeks, days, minutes,secondsが利用できる。
複数の単位を指定する場合は以下のようにする。
datetime.timedelta(days=7, hours=1, seconds=10)


詳細:簡単にできる単位別の+、-、
https://qiita.com/7110/items/4ece0ce9be0ce910ee90

◇Daylight Saving Time の考慮

いわゆる夏時間というもので、
ESTだと、 UTCの  - 5 hours
EDTだと、UTCの  - 4 hours
時間となり、1年のうちに時間差が変更になる。

それでも、EST/EDTの変更日が決まっていれば、計算できそうだけど、

アメリカのDaylight Saving Time (DST)は、

In the U.S., daylight saving time starts on the second Sunday in March and ends on the first Sunday in November, with the time changes taking place at 2:00 a.m. local time

となっていて、毎年、適用開始/終了日が異なる。

なので自分でCodeするのは諦めて、Python の3rd Partyの Libraryを使った方が良い。

import pytz
from datetime import datetime


et = pytz.timezone('US/Eastern')
utc= pytz.utc
fmt = "%Y-%m-%d %H:%M:%S %Z%z"
fmt2= "%Y-%m-%d %H:%M:%S "


for tweet in tweets:
    print("Original Created_at")
    print(tweet.created_at)
    est_time = tweet.created_at.astimezone(et)
    print("Converted Time")
    print(est_time)
   
    est_localize = est_time.strftime(fmt)
    print("with fmt")
    print(est_localize)


    est_localize2 = est_time.strftime(fmt2)
    print("with fmt2")
    print(est_localize2)


#Output
Original Created_at
2019-05-19 12:49:33
Converted Time
2019-05-18 23:49:33-04:00
with fmt
2019-05-18 23:49:33 EDT-0400
with fmt2
2019-05-18 23:49:33



How to convert UTC to EST with Python and take care of daylight saving automatically?


https://stackoverflow.com/questions/48416511/how-to-convert-utc-to-est-with-python-and-take-care-of-daylight-saving-automatic/48417012#48417012

◇tweepyで取得するcreated.atについて

Thu Apr 23 13:38:19 +0000 2019
の書式で取得できるので、もう少し工夫が必要


以下が完成版。

#Twitter の created_at は、 utcで記録されていますが、datetime objには、timezone情報を持っていません。 そこで、utc であることをtimezone情報にもたせてから、Estern timeに変換します。
(Datetime objがタイムゾーン情報をもっているか(awareであるか)の調べ方は次の投稿 -実践編で)

import datetime
from datetime import datetime,date
import pytz

tweets = extractor.user_timeline(screen_name="realDonaldTrump", count=3,include_rts=True,tweet_mode="extended")

et = pytz.timezone('US/Eastern')
utc = pytz.utc
fmt = "%Y-%m-%d %H:%M:%S"

for tweet in tweets:

    reformatted_created_at =tweet.created_at.strftime('%Y-%m-%d %H:%M:%S')
    reformatted_created_at2 = datetime.strptime(reformatted_created_at,"%Y-%m-%d %H:%M:%S").replace(tzinfo=pytz.UTC)

    est_time = reformatted_created_at2.astimezone(et)

    print(est_time)

となる。

以下は、この結論になるまでのテスト。

********************************************************

1. Basic datetime
import datetime

now = datetime.datetime.now(tz=datetime.timezone.utc)
print(now)
Outoput:
2019-05-20 00:26:15.510768+00:00
*naive vs aware time zone info
now = datetime.datetime.now() #naive : 2019-05-20 00:40:37.940085  

2.Utilize pytz
import datetime
import pytz

now = datetime.datetime.now(tz=datetime.timezone.utc)
print(now) #2019-05-20 00:45:02.737131+00:00
jst = pytz.timezone('Asia/Tokyo')
jst_now = datetime.datetime.now(tz=jst)
print(jst_now) #2019-05-20 09:45:02.739732+09:00 
et = pytz.timezone('US/Eastern')
fmt = "%Y-%m-%d %H:%M:%S"
est_time = now.astimezone(et)
jst_to_et =jst_now.astimezone(et)
print(est_time) #2019-05-19 20:45:02.737131-04:00 
print(jst_to_et)#2019-05-19 20:45:02.737131-04:00 

★created_at : format
Basic format:Thu Apr 23 13:38:19 +0000 200
import datetime
from datetime import datetime,date
import pytz
created_at="Thu Apr 23 13:38:19 +0000 2009"
modified =datetime.strptime(created_at,'%a %b %d %H:%M:%S +0000 %Y').replace(tzinfo=pytz.UTC)
print(modified)
#output: 2009-04-23 13:38:19+00:00 
*daytime.strptimeは、
from datetime import datetime,date is imperative to use.

(Sample Tested)
import datetime
from datetime import datetime,date
import pytz
created_at="Thu Apr 23 13:38:19 +0000 2009"
print(created_at)
reformatted_created_at =datetime.strptime(created_at,'%a %b %d %H:%M:%S +0000 %Y').replace(tzinfo=pytz.UTC)
print('reformatted')
print(reformatted_created_at)
et = pytz.timezone('US/Eastern')
fmt = "%Y-%m-%d %H:%M:%S"
est_time = reformatted_created_at.astimezone(et)
est_time_fmt=est_time.strftime(fmt)
print(est_time)
print(est_time_fmt)
output:
Thu Apr 23 13:38:19 +0000 2009                                                 
reformatted                                                                    
2009-04-23 13:38:19+00:00                                                      
2009-04-23 09:38:19-04:00                                                      
2009-04-23 09:38:19


① Trumpのツイート(13:25 - 2019年5月19日)を、②LouDobbs氏がQuoteしてツイートし、、③それを再度、Trump氏がリツイート。
この場合、最初の'created_at'に記載されているのが、Trump氏の最後のリツイート時間③。
但し、Twitterページで確認できる時間は、②のQuoteツイートした時間。
且つ、Twitterページで確認できるのは、Tweetした人 'LouDobbs氏' のローカル・タイム(ET)。
又、<blockquote class="twitter-tweet">でWeb表示した場合、'LouDobbs氏' のツイートの時間を、
Web閲覧者の時間に変更して表示(JST)
従って、いずれのWebで表示できる時間とは異なるものの、Trump氏がいつツイートをしたかを
知りたいのであれば、最初のcreated_atを参照することが正しい。
Tweet Objectに含まれる3種類のcreated_at:
 _json={
'created_at': 'Mon May 20 02:47:21 +0000 2019', ・・・③
'retweeted_status': {
'created_at': 'Sun May 19 23:34:46 +0000 2019',  ・・・②
'quoted_status': 'created_at': 'Sun May 19 20:25:34 +0000 2019・・・①でもないよう。

1) <blockquote class="twitter-tweet">でのPC上のWebに表示される時間:
8:34 - 2019年5月20日 (utc +9:00時間)
2) TwitterのPCページで表示される時間
16:34 - 2019年5月19日 (utc -4:00時間)- Trumpのリツイート時間ではない。

◇①のツイートの時間
1)Mobile APP;
5:25am 20 May 19

2019年5月18日土曜日

get.oembed()


get.oembed()

def trump_list():
     texts=[]
     for t in tw.Cursor(extractor.search,q="Trump China" + ' -filter:retweets',lang='en').items(10):
          tweet= t.id
          oembed = extractor.get_oembed(id=tweet, hide_media=False, hide_thread=True)
          texts.append(oembed['html'])
     return render_template("trump_list.html", texts = texts)

2019年5月12日日曜日

Pandasのデータフレームに使う小技


pandasのデータフレームを操作する時によく使う小技をまとめておきます。

◇ラベルの追加
tweet_df = pd.DataFrame(data=[[tweet.created_at,tweet.full_text,tweet.favorite_count,tweet.retweet_count] for tweet in tweets],
                                    columns=['Date','Tweet','Like','RT'])

tweet_df['SA'] = np.array([ analize_sentiment(tweet) for tweet in tweet_df['Tweet'] ])


◇ソート
tweet_df_sorted = tweet_df.sort_values('RT', ascending=False)

注)ソートすると、Index番号自身もソートされてしまう。
(ソート前)
                 Date
0 2019-05-30 11:21:45
1 2019-05-30 00:59:43
2 2019-05-30 00:46:39
3 2019-05-30 00:32:06
4 2019-05-29 17:23:55

(ソート後)
                 Date
3 2019-05-30 00:32:06
1 2019-05-30 00:59:43
2 2019-05-30 00:46:39
0 2019-05-30 11:21:45
4 2019-05-29 17:23:55


◇重複データの抽出・削除
duplicated()メソッド:
デフォルトは全部一致の場合、重複と判断。 列を指定して判断する場合、

print(tweet_df.duplicated(subset='RT'))

(Output)
45    False
66    False
75     True
93     True
37     True
69     True
重複しているデータの1つ目は、重複していないものとしてFalseが返される。


◇重複データの削除
print(df.drop_duplicates(subset='RT'))
                  Date                                              Tweet  Like    RT  SA
38 2019-05-12 06:07:30  RT @LindseyGrahamSC: Will stand behind Preside...     0  6959   1
23 2019-05-12 06:08:40  RT @LindseyGrahamSC: When it comes to China, t...     0  5875   1
56 2019-05-12 06:05:45  RT @PalmerReport: This is an actual sentence f...        0  5845   1
26 2019-05-12 06:08:24  RT @danpfeiffer: Trump is engaged in an unprec...       0  1353   1


◇Columnを指定してPrintout
print(df['Tweet'])

38    RT @LindseyGrahamSC: Will stand behind Preside...
23    RT @LindseyGrahamSC: When it comes to China, t...
56    RT @PalmerReport: This is an actual sentence f...
26    RT @danpfeiffer: Trump is engaged in an unprec...


◇pandas フレームワークの要素の表示

(htmlでの記述)

    ◇ Latest tweet by President Trump
     <p>{{tweet_df.iloc[0].Date}}</p>
     <p>{{tweet_df.iloc[0].Tweet}}</p>
     <p><span class="text-primary"><i class="fas fa-heart"></i></span>  {{tweet_df.iloc[0].Like}}
        <span class="text-primary"><i class="fas fa-retweet"></i></span>{{tweet_df.iloc[0].RT}}</p>




2019年5月10日金曜日

Tweet Status Object Structure


user_timeline( ) で取得されるのは、Status Objectを含む、Tweepy Result set。 このお蔭で

for tweet in tweets:
    tweet.created_at

の形式で、各要素にアクセスできる。
print(tweets) #<class 'tweepy.models.ResultSet'>



<Simple Tweet>
Status(_api=<tweepy.api.API object at 0x0000000003610F60>,
_json={'created_at': 'Fri May 10 11:43:30 +0000 2019', 'id': 1126815018253557760, 'id_str': '1126815018253557760',
'text': '"Don\'tworry about it! It will all work out. You know why? It always does."\n-by President Donald Trump\n\nWhat a powe… https://t.co/SyGjwvItqo',
'truncated': True,
'entities': {'hashtags': [], 'symbols': [], 'user_mentions': [], 'urls': [{'url': 'https://t.co/SyGjwvItqo', 'expanded_url':'https://twitter.com/i/web/status/1126815018253557760', 'display_url': 'twitter.com/i/web/status/1…', 'indices': [117, 140]}]}, 'source': '<a href="http://twitter.com" rel="nofollow">Twitter Web Client</a>', 'in_reply_to_status_id': None, 'in_reply_to_status_id_str': None, 'in_reply_to_user_id': None, 'in_reply_to_user_id_str': None, 'in_reply_to_screen_name': None, 'user': {'
id': 1118188831948230657, 'id_str': '1118188831948230657', 'name': 'kappamobestjp', 'screen_nam
e': 'kappamobestjp', 'location': 'United States', 'description': '', 'url': None, 'entities': {
'description': {'urls': []}}, 'protected': False, 'followers_count': 0, 'friends_count': 4, 'li
sted_count': 0, 'created_at': 'Tue Apr 16 16:26:07 +0000 2019', 'favourites_count': 1, 'utc_off
set': None, 'time_zone': None, 'geo_enabled': False, 'verified': False, 'statuses_count': 7, 'l
ang': 'en', 'contributors_enabled': False, 'is_translator': False, 'is_translation_enabled': Fa
lse, 'profile_background_color': 'F5F8FA', 'profile_background_image_url': None, 'profile_backg
round_image_url_https': None, 'profile_background_tile': False, 'profile_image_url': 'http://ab
s.twimg.com/sticky/default_profile_images/default_profile_normal.png', 'profile_image_url_https
': 'https://abs.twimg.com/sticky/default_profile_images/default_profile_normal.png', 'profile_l
ink_color': '1DA1F2', 'profile_sidebar_border_color': 'C0DEED', 'profile_sidebar_fill_color': '
DDEEF6', 'profile_text_color': '333333', 'profile_use_background_image': True, 'has_extended_pr
ofile': False, 'default_profile': True, 'default_profile_image': True, 'following': False, 'fol
low_request_sent': False, 'notifications': False, 'translator_type': 'none'}, 'geo': None, 'coo
rdinates': None, 'place': None, 'contributors': None, 'is_quote_status': False, 'retweet_count'
: 0, 'favorite_count': 0, 'favorited': False, 'retweeted': False, 'lang': 'en'}, created_at=dat
etime.datetime(2019, 5, 10, 11, 43, 30), id=1126815018253557760, id_str='1126815018253557760',
text='"Don\'t worry about it! It will all work out. You know why? It always does."\n-by Preside
nt Donald Trump\n\nWhat a powe… https://t.co/SyGjwvItqo', truncated=True, entities={'hashtags'
: [], 'symbols': [], 'user_mentions': [], 'urls': [{'url': 'https://t.co/SyGjwvItqo', 'expanded
_url': 'https://twitter.com/i/web/status/1126815018253557760', 'display_url': 'twitter.com/i/we
b/status/1…', 'indices': [117, 140]}]}, source='Twitter Web Client', source_url='http://twitte
r.com', in_reply_to_status_id=None, in_reply_to_status_id_str=None, in_reply_to_user_id=None, i
n_reply_to_user_id_str=None, in_reply_to_screen_name=None, author=User(_api=<tweepy.api.API obj
ect at 0x0000000003610F60>, _json={'id': 1118188831948230657, 'id_str': '1118188831948230657',
'name': 'kappamobestjp', 'screen_name': 'kappamobestjp', 'location': 'United States', 'descript
ion': '', 'url': None, 'entities': {'description': {'urls': []}}, 'protected': False, 'follower
s_count': 0, 'friends_count': 4, 'listed_count': 0, 'created_at': 'Tue Apr 16 16:26:07 +0000 20
19', 'favourites_count': 1, 'utc_offset': None, 'time_zone': None, 'geo_enabled': False, 'verif
ied': False, 'statuses_count': 7, 'lang': 'en', 'contributors_enabled': False, 'is_translator':
 False, 'is_translation_enabled': False, 'profile_background_color': 'F5F8FA', 'profile_backgro
und_image_url': None, 'profile_background_image_url_https': None, 'profile_background_tile': Fa
lse, 'profile_image_url': 'http://abs.twimg.com/sticky/default_profile_images/default_profile_n
ormal.png', 'profile_image_url_https': 'https://abs.twimg.com/sticky/default_profile_images/def
ault_profile_normal.png', 'profile_link_color': '1DA1F2', 'profile_sidebar_border_color': 'C0DE
ED', 'profile_sidebar_fill_color': 'DDEEF6', 'profile_text_color': '333333', 'profile_use_backg
round_image': True, 'has_extended_profile': False, 'default_profile': True, 'default_profile_im
age': True, 'following': False, 'follow_request_sent': False, 'notifications': False, 'translat
or_type': 'none'}, id=1118188831948230657, id_str='1118188831948230657', name='kappamobestjp',
screen_name='kappamobestjp', location='United States', description='', url=None, entities={'des
cription': {'urls': []}}, protected=False, followers_count=0, friends_count=4, listed_count=0,
created_at=datetime.datetime(2019, 4, 16, 16, 26, 7), favourites_count=1, utc_offset=None, time
_zone=None, geo_enabled=False, verified=False, statuses_count=7, lang='en', contributors_enable
d=False, is_translator=False, is_translation_enabled=False, profile_background_color='F5F8FA',
profile_background_image_url=None, profile_background_image_url_https=None, profile_background_
tile=False, profile_image_url='http://abs.twimg.com/sticky/default_profile_images/default_profi
le_normal.png', profile_image_url_https='https://abs.twimg.com/sticky/default_profile_images/de
fault_profile_normal.png', profile_link_color='1DA1F2', profile_sidebar_border_color='C0DEED',
profile_sidebar_fill_color='DDEEF6', profile_text_color='333333', profile_use_background_image=
True, has_extended_profile=False, default_profile=True, default_profile_image=True, following=F
alse, follow_request_sent=False, notifications=False, translator_type='none'), user=User(_api=<
tweepy.api.API object at 0x0000000003610F60>, _json={'id': 1118188831948230657, 'id_str': '1118
188831948230657', 'name': 'kappamobestjp', 'screen_name': 'kappamobestjp', 'location': 'United
States', 'description': '', 'url': None, 'entities': {'description': {'urls': []}}, 'protected'
: False, 'followers_count': 0, 'friends_count': 4, 'listed_count': 0, 'created_at': 'Tue Apr 16
 16:26:07 +0000 2019', 'favourites_count': 1, 'utc_offset': None, 'time_zone': None, 'geo_enabl
ed': False, 'verified': False, 'statuses_count': 7, 'lang': 'en', 'contributors_enabled': False
, 'is_translator': False, 'is_translation_enabled': False, 'profile_background_color': 'F5F8FA'
, 'profile_background_image_url': None, 'profile_background_image_url_https': None, 'profile_ba
ckground_tile': False, 'profile_image_url': 'http://abs.twimg.com/sticky/default_profile_images
/default_profile_normal.png', 'profile_image_url_https': 'https://abs.twimg.com/sticky/default_
profile_images/default_profile_normal.png', 'profile_link_color': '1DA1F2', 'profile_sidebar_bo
rder_color': 'C0DEED', 'profile_sidebar_fill_color': 'DDEEF6', 'profile_text_color': '333333',
'profile_use_background_image': True, 'has_extended_profile': False, 'default_profile': True, '
default_profile_image': True, 'following': False, 'follow_request_sent': False, 'notifications'
: False, 'translator_type': 'none'}, id=1118188831948230657, id_str='1118188831948230657', name
='kappamobestjp', screen_name='kappamobestjp', location='United States', description='', url=No
ne, entities={'description': {'urls': []}}, protected=False, followers_count=0, friends_count=4
, listed_count=0, created_at=datetime.datetime(2019, 4, 16, 16, 26, 7), favourites_count=1, utc
_offset=None, time_zone=None, geo_enabled=False, verified=False, statuses_count=7, lang='en', c
ontributors_enabled=False, is_translator=False, is_translation_enabled=False, profile_backgroun
d_color='F5F8FA', profile_background_image_url=None, profile_background_image_url_https=None, p
rofile_background_tile=False, profile_image_url='http://abs.twimg.com/sticky/default_profile_im
ages/default_profile_normal.png', profile_image_url_https='https://abs.twimg.com/sticky/default
_profile_images/default_profile_normal.png', profile_link_color='1DA1F2', profile_sidebar_borde
r_color='C0DEED', profile_sidebar_fill_color='DDEEF6', profile_text_color='333333', profile_use
_background_image=True, has_extended_profile=False, default_profile=True, default_profile_image
=True, following=False, follow_request_sent=False, notifications=False, translator_type='none')
, geo=None, coordinates=None, place=None, contributors=None, is_quote_status=False, retweet_cou
nt=0, favorite_count=0, favorited=False, retweeted=False, lang='en')

◇連続投稿
(引用した方には、引用元のTweet情報がEncloseされている。
 引用元の 'in_reply_to_status_id': が紐付いている)



Status(_api=<tweepy.api.API object at 0x0000000003612F28>,
_json={'created_at': 'Fri May 10 11:12:55 +0000 2019',
  'id': 1126807322666209281, 'id_str': '1126807322666209281',
  'text': '”何があっても心配することないよ。全部、上手くいくんだから。何故か知ってる?\u3000だって、そういうも
     のだから!”\u3000記者を前に、こんな発言、いろんな意味で凄すぎる!!\n\n
     トランプ大統領のツイート分析始めました。… https://t.co/i36pmW6UHG',
  'truncated': True,
  'entities': {   'hashtags': [],
      'symbols': [],
      'user_mentions': [],
      'urls': [{'url': 'https://t.co/i36pmW6UHG',
      'expanded_url':'https://twitter.com/i/web/status/1126807322666209281',
      'display_url': 'twitter.com/i/web/status/1…',
      'indices': [104, 127]}]},
      'source': '<a href="http://twitter.com" rel="nofollow">Twitter Web Client</a>',
      'in_reply_to_status_id': 1126807319004700672,
      'in_reply_to_status_id_str':'1126807319004700672',
      'in_reply_to_user_id': 1118188831948230657,
      'in_reply_to_user_id_str': '1118188831948230657',
      'in_reply_to_screen_name': 'kappamobestjp',
      'user': {'id': 1118188831948230657,
        'id_str': '1118188831948230657',
        'name': 'kappamobestjp',
        'screen_name': 'kappamobestjp',
        'location': 'United States',
        'description': '',
        'url': None,
     'entities': {'description': {'urls': []}}, 'protected': False, 'followers_count': 0, 'friends_count': 4,
       'listed_count': 0, 'created_at': 'Tue Apr 16 16:26:07 +0000 2019', 'favourites_count': 1,
       'utc_offset': None, 'time_zone': None, 'geo_enabled': False, 'verified': False, 'statuses_count': 6, 'lang': 'en', 'contributors_enabled': False, 'is_translator': False, 'is_translation_enabled': False, 'profile_background_color': 'F5F8FA', 'profile_background_image_url': None, 'profile_background_image_url_https': None, 'profile_background_tile': False, 'profile_image_url': 'http://abs.twimg.com/sticky/default_profile_images/default_profile_normal.png', 'profile_image_url_https': 'https://abs.twimg.com/sticky/default_profile_images/default_profile_normal.png', 'profile_link_color': '1DA1F2', 'profile_sidebar_border_color': 'C0DEED', 'profile_sidebar_fill_color': 'DDEEF6',
       'profile_text_color': '333333', 'profile_use_background_image': True, 'has_extended_profile': False,
       'default_profile': True, 'default_profile_image': True, 'following': False, 'follow_request_sent':False, 'notifications': False, 'translator_type': 'none'}, 'geo': None, 'coordinates': None, 'place': None, 'contributors': None, 'is_quote_status': False, 'retweet_count': 0, 'favorite_count': 0, 'favorited': False, 'retweeted': False, 'possibly_sensitive': False, 'lang': 'ja'}, created_at=datetime.datetime(2019, 5, 10, 11, 12, 55), id=1126807322666209281, id_str='1126807322666209281', text='”何があっても心配することないよ。全部、上手くいくんだから。何故か知ってる?\u3000
       だって、そういうものだから!”\u3000記者を前に、こんな発言、いろんな意味で凄すぎる!!\n\n
       トランプ大統領のツイート分析始めました。… https://t.co/i36pmW6UHG', truncated=True,
       entities={'hashtags': [], 'symbols': [], 'user_mentions': [], 'urls': [{'url': 'https://t.co/i36pmW6UHG', 'expanded_url': 'https://twitter.com/i/web/status/1126807322666209281',
       'display_url': 'twitter.com/i/web/status/1…', 'indices': [104, 127]}]}, source='Twitter Web Client', source_url='http://twitter.com', in_reply_to_status_id=1126807319004700672, in_reply_to_status_id_str='1126807319004700672', in_reply_to_user_id=1118188831948230657, in_reply_to_user_id_str='1118188831948230657', in_reply_to_screen_name='kappamobestjp', author=User(_api=<tweepy.api.API object at 0x0000000003612F28>, _json={'id': 1118188831948230657, 'id_str': '1118188831948230657', 'name': 'kappamobestjp', 'screen_name': 'kappamobestjp', 'location': 'United States', 'description': '', 'url': None, 'entities': {'description': {'urls': []}}, 'protected': False, 'followers_count': 0, 'friends_count': 4, 'listed_count': 0, 'created_at': 'Tue Apr 16 16:26:07 +0000 2019', 'favourites_count': 1, 'utc_offset': None, 'time_zone': None, 'geo_enabled': False, 'verified': False, 'statuses_count': 6, 'lang': 'en', 'contributors_enabled': False, 'is_translator': False, 'is_translation_enabled': False, 'profile_background_color': 'F5F8FA', 'profile_background_image_url': None, 'profile_background_image_url_https': None, 'profile_background_tile': False, 'profile_image_url': 'http://abs.twimg.com/sticky/default_profile_images/default_profile_normal.png',
       'profile_image_url_https': 'https://abs.twimg.com/sticky/default_profile_images/default_profile_normal.png',
       'profile_link_color': '1DA1F2', 'profile_sidebar_border_color': 'C0DEED',
       'profile_sidebar_fill_color': 'DDEEF6', 'profile_text_color': '333333',
       'profile_use_background_image': True, 'has_extended_profile': False, 'default_profile': True, 'default_profile_image': True,'following': False, 'follow_request_sent': False, 'notifications': False, 'translator_type': 'none'}, id=1118188831948230657, id_str='1118188831948230657', name='kappamobestjp', screen_name='kappamobestjp', location='United States', description='', url=None, entities={'description': {'urls': []}}, protected=False, followers_count=0, friends_count=4, listed_count=0, created_at=datetime.datetime(2019, 4, 16, 16, 26, 7), favourites_count=1, utc_offset=None, time_zone=None,geo_enabled=False, verified=False, statuses_count=6, lang='en', contributors_enabled=False, is_translator=False, is_translation_enabled=False, profile_background_color='F5F8FA', profile_background_image_url=None, profile_background_image_url_https=None, profile_background_tile=False,profile_image_url='http://abs.twimg.com/sticky/default_profile_images/default_profile_normal.png', profile_image_url_https='https://abs.twimg.com/sticky/default_profile_images/default_profile_normal.png', profile_link_color='1DA1F2', profile_sidebar_border_color='C0DEED', profile_sidebar_fill_color='DDEEF6', profile_text_color='333333', profile_use_background_image=True, has_extended_profile=False, default_profile=True, default_profile_image=True, following=False,
       follow_request_sent=False, notifications=False, translator_type='none'),
       user=User(_api=<tweepy.api.API object at 0x0000000003612F28>,
       _json={'id': 1118188831948230657, 'id_str': '1118188831948230657', 'name': 'kappamobestjp', 'screen_name': 'kappamobestjp', 'location': 'United States', 'description': '', 'url': None, 'entities': {'description': {'urls': []}}, 'protected': False, 'followers_count': 0, 'friends_count': 4, 'listed_count': 0, 'created_at': 'Tue Apr 16 16:26:07 +0000 2019', 'favourites_count': 1, 'utc_offset': None, 'time_zone': None, 'geo_enabled': False,'verified': False, 'statuses_count': 6, 'lang': 'en', 'contributors_enabled': False, 'is_translator': False, 'is_translation_enabled': False, 'profile_background_color': 'F5F8FA', 'profile_background_image_url': None, 'profile_background_image_url_https': None, 'profile_background_tile': False, 'profile_image_url': 'http://abs.twimg.com/sticky/default_profile_images/default_profile_normal.png', 'profile_image_url_https': 'https://abs.twimg.com/sticky/default_profile_images/default_profile_normal.png', 'profile_link_color': '1DA1F2', 'profile_sidebar_border_color': 'C0DEED', 'profile_sidebar_fill_color': 'DDEEF6', 'profile_text_color': '333333', 'profile_use_background_image': True, 'has_extended_profile': False, 'default_profile': True, 'default_profile_image': True, 'following': False, 'follow_request_sent': False, 'notifications': False, 'translator_type': 'none'}, id=1118188831948230657, id_str='1118188831948230657', name='kappamobestjp', screen_name='kappamobestjp', location='United States', description='', url=None, entities={'description': {'urls': []}}, protected=False, followers_count=0, friends_count=4, listed_count=0, created_at=datetime.datetime(2019, 4, 16, 16, 26, 7), favourites_count=1, utc_offset=None, time_zone=None, geo_enabled=False, verified=False, statuses_count=6, lang='en', contributors_enabled=False, is_translator=False, is_translation_enabled=False, profile_background_color='F5F8FA', profile_background_image_url=None, profile_background_image_url_https=None, profile_background_tile=False, profile_image_url='http://abs.twimg.com/sticky/default_profile_images/default_profile_normal.png', profile_image_url_https='https://abs.twimg.com/sticky/default_profile_images/default_profile_normal.png', profile_link_color='1DA1F2', profile_sidebar_border_color='C0DEED', profile_sidebar_fill_color='DDEEF6', profile_text_color='333333', profile_use_background_image=True, has_extended_profile=False, default_profile=True, default_profile_image=True, following=False, follow_request_sent=False, notifications=False, translator_type='none'), geo=None,coordinates=None, place=None, contributors=None, is_quote_status=False, retweet_count=0, favorite_count=0, favorited=False, retweeted=False, possibly_sensitive=False, lang='ja')

2019年5月9日木曜日

tweepyでreply tweetにアクセスする方法

user.user_timelineで取得できるデータを再確認する。

tweetした人
tweets = extractor.user_timeline(screen_name="realDonaldTrump", count=30)



◇ Replyのデータを取得する

How to get the replies for a given tweet with tweepy and python?

https://stackoverflow.com/questions/52307443/how-to-get-the-replies-for-a-given-tweet-with-tweepy-and-python

(Sep 13 '18 at 5:55)

This code will fetch 10 recent tweets of an user(name) along with the replies to that particular tweet.


これで取得できます。 

<tweepyで接続した後で>


replies=[]

non_bmp_map = dict.fromkeys(range(0x10000, sys.maxunicode + 1), 0xfffd) for full_tweets in tweepy.Cursor(api.user_timeline,screen_name='tartecosmetics',timeout=999999).items(10):

  for tweet in tweepy.Cursor(api.search,q='to:'+'tartecosmetics',result_type='recent',timeout=999999).items(1000):

    if hasattr(tweet, 'in_reply_to_status_id_str'):

      if (tweet.in_reply_to_status_id_str==full_tweets.id_str):

        replies.append(tweet.text)

  print("Tweet :",full_tweets.text.translate(non_bmp_map))

  for elements in replies:

       print("Replies :",elements)

  replies.clear()



解説)

dict.fromkeys():creates a new dictionary from the given sequence of elements with a value provided by the user.

dictionary.fromkeys(sequence[, value])

例)
# vowels keys
keys = {'a', 'e', 'i', 'o', 'u' }
value = [1]
vowels = dict.fromkeys(keys, value)
print(vowels)

{'a': [1], 'u': [1], 'o': [1], 'e': [1], 'i': [1]}

https://www.programiz.com/python-programming/methods/dictionary/fromkeys

0x10000:Numbers that begin with 0x are interpreted as hexadecimal (base 16) in C.
So, 0x10000 is 16*16*16*16 = 16^4 = 65536
sys.maxunicode: Unicode コードポイントの最大値を示す整数、すなわち 1114111 (16 進数で 0x10FFFF) です。

0xfffd: UTF-8の文字表示



**以下代表的、Logフォーマットなので面倒。。

Code:

user_name = "@nameofuser"

replies = tweepy.Cursor(api.search, q='to:{}'.format(user_name),

                                since_id=tweet_id, tweet_mode='extended').items() while True:

    try:

        reply = replies.next()

        if not hasattr(reply, 'in_reply_to_status_id_str'):

            continue

        if reply.in_reply_to_status_id == tweet_id:

           logging.info("reply of tweet:{}".format(reply.full_text))



    except tweepy.RateLimitError as e:

        logging.error("Twitter api rate limit reached".format(e))

        time.sleep(60)

        continue



    except tweepy.TweepError as e:

        logging.error("Tweepy error occured:{}".format(e))

        break



    except StopIteration:

        break



    except Exception as e:

        logger.error("Failed while fetching replies {}".format(e))

        break





◇Retweet を取得する。





◇Tweet Object

https://developer.twitter.com/en/docs/tweets/data-dictionary/overview/tweet-object.html

hasattr():指定のオブジェクトが特定の属性を持っているかを確認するhasattr関数.

属性を持っているとTrue、属性は持っていないためFalse値を返す。

since_id:

in_reply_to_status_id_str: Nullable. If the represented Tweet is a reply, this field will contain the string representation of the original Tweet’s ID. Example:

logging.info/ logging.error: Log情報の記録。

https://qiita.com/__init__/items/91e5841ed53d55a7895e

import logging が必要

logging のみの書き方:logging.info('info %s %s', 'test', 'test')



◇Textblob

1) https://www.codementor.io/ferrorodolfo/sentiment-analysis-on-trump-s-tweets-using-python-pltbvb4xr

''' Utility function to clean the text in a tweet by removing links and special characters using regex.'''

    return ' '.join(re.sub("(@[A-Za-z0-9]+)|([^0-9A-Za-z \t])|(\w+:\/\/\S+)", " ", tweet).split())

Percentage of positive tweets: 51.0% Percentage of neutral tweets: 27.0% Percentage de negative tweets: 22.0%





(解説)

' '. :区切り文字をつけないで連結。

test = ['ab', 'c', 'de']

result = ''.join(test)

print(result):abcde

result2 = ','.join(test)

print(result2): ab,c,de



.split() : ()内の文字で分割する。

a = "abbaccadda"

sep = a.split("a")

print(sep) : ['', 'bb', 'cc', 'dd', '']

sep2 = a.split("ac")

print(sep2)

['abb', 'cadda']

*区切りに使用した文字列は、戻り値からは消えてしまう。



re.sub():re.sub(正規表現, “置換する文字列”, 置換対象の文字列)

[★] ★のどれか1文字





Python

import re



message="My office email address is test2018@test.com.But my personal one is test.craig@g.co.jp.Please visit our web site @ https://test.test.com. Company information is here at https://test.test.com/about Sincerely, 15 Jan, 2019 "



new_message=' '.join(re.sub("(@[A-Za-z0-9]+)|([^0-9A-Za-z \t])|(\w+:\/\/\S+)", " ", message).split())



print(new_message)





Output:

My office email address is test2018 com But my personal one is test craig co jp Please visit our web site Company information is here at Sincerely 15 Jan 2019





My office email address is test2018@test.com. But my personal one is test.craig@g.co.jp.
Please visit our web site @ https://test.test.com.
Company information is here at https://test.test.com/about
Sincerely,
15 Jan, 2019



Python







2) https://www.geeksforgeeks.org/twitter-sentiment-analysis-using-python/

'''Utility function to clean tweet text by removing links, special characters using simple regex statements. '''

    return ' '.join(re.sub("(@[A-Za-z0-9]+)|([^0-9A-Za-z \t]) |(\w+:\/\/\S+)", " ", tweet).split()) return ' '.join(re.sub("(@[A-Za-z0-9]+)|([^0-9A-Za-z \t])

                                    |(\w+:\/\/\S+)", " ", tweet).split())



2019年5月7日火曜日

FLASKのコツ APPをリフレッシュする方法


1. htmlにリフレッシュ・ボタンをつける。

<a href="{{ url_for('index') }}"><button>REFRESH</button></a>
      最新の数字にRefresh
これだけで、Refreshされる。

2. IEへの対処
PC とAndroid Chromeは、上記だけでリフレッシュされるが、PCのブラウザがIEだと上手く
リフレッシュされない。

そこで、Flask側でCasheをコントロールする。

@app.after_request
def apply_caching(response):
     response.headers['Cache-Control'] = 'no-cache, no-store, must-revalidate'
     return response

これでIEも、1のボタンでリフレッシュできるようになる。

というか、F5ボタンを押してもらえればリフレッシュされるのですが、それではカッコよくないので。