PythonからTwitterにツイートしてみる

投稿者: | 2021年5月14日

Pythonを諸々お勉強中の私。
今日は、サクッとTwitterにツイートするスクリプトを御紹介する。

サクッとと表現したが、めっちゃつまづきまくって辿り着いているので、今後の自分のためにメモをする程度の記事なので悪しからず。

○動くスクリプトの御紹介
○ハマったポイントの御紹介
という文章構成でお話ししていきます。

まず、必要なものを記す。

○Twitterのアカウント(テスト時は鍵アカウントにした方が良き)
○TwitterのDeveloper登録(色々手続きがあるので、
手順は「Twitter APIキー 取得」とかで検索してみて下さい。)
○上記で取得出来る以下の4つ
・APIキー
・APIシークレットキー
・アクセストークン
・アクセストークンシークレット

※難しいことはわからんので、解説は他サイトに任せ、ここでは書きません。

で、スクリプトのファイル構成を以下に記す。

env.json
tweetClass.py
tweet.py

※サクッとと言ってみたものの、一応キーはハードコードしない、クラスは外だしする。

env.jsonには、TwitterのAPIキーを記述する。

{
“tweetkey”:{
“akey”:”ここにAPIキーをコピペ”,
“skey”:”ここにAPIシークレットをコピペ”,
“token”:”ここにアクセストークンをコピペ”,
“tokensecret”:”ここにトークンシークレットを(略”,
“bearer”:”今回ベアラーは使わないけど、メモがてらコピペ”
}
}

※全角スペース入ってたらごめんなさい。多分大丈夫だけど。

tweetClass.pyは以下。

import json
import twitter

class tweetClass:
#coding: UTF-8
def tweettest(message):
tweetkey = open(‘env.json’, ‘r’)
tweetkeyLoad = json.load(tweetkey)
access_token = tweetkeyLoad[‘tweetkey’][‘akey’]
access_token_secret = tweetkeyLoad[‘tweetkey’][‘skey’]
api_key = tweetkeyLoad[‘tweetkey’][‘token’]
api_secret = tweetkeyLoad[‘tweetkey’][‘tokensecret’]
tweetkey.close()
# 取得したキーとアクセストークンを設定する(冗長なコードだけど、型変換のために必要)
auth = twitter.OAuth(
consumer_key = str(access_token),
consumer_secret = str(access_token_secret),
token = str(api_key),
token_secret = str(api_secret)
)
t = twitter.Twitter(auth = auth)

# twitterへメッセージを投稿する
return t.statuses.update(status = str(message))

※全角スペース混じってたらごめんなさい。

最後にtweet.pyは以下。

import tweetClass
import datetime

dt_now = datetime.datetime.now()
tweetTest = tweetClass.tweetClass
message = “これはテストツイートです\n” + str(dt_now)
try:
tweetTest.tweettest(message)
except Exception as e:
logMessage = ‘エラー:\n’ + str(e) + ‘\n’ +str(type(e)) + ‘\n’ + str(e.args)
print(logMessage)

色々、つまづいてやっと動くようになったスクリプトが以上です。

では、何につまづいたかというと。。。

details: {‘errors’: [{‘code’: 89, ‘message’: ‘Invalid or expired token.’}]}

こんなエラーが出てました。
初めはキーが間違ってるのか?とキーを再生成したりしてみたのですが、切り分けの結果、APIキーたちをスクリプトに直接書いている時は出なくて、Jsonからのキー呼び出しに変更したら発生することがわかりました。
どうやら、Jsonロードした値はstr( )でString型にしてあげないと、認証エラーになっちゃうみたいです。

次に

details: {‘errors’: [{‘code’: 187, ‘message’: ‘Status is a duplicate.’}]}

このエラー。
これは、全く同じ文やテキストをツイートした場合、「そのツイートはカブってるぜ!」ってエラーみたいです。全く同じ文章はツイート出来ないみたい。
なので、datetime.now()を使ってタイムスタンプを付けてやるようにしています。

結構ハマったのが、コレ。

TypeError: ‘module’ object is not callable

これは、当初、tweetClass.pyの中でインスタンス生成して、メソッドをコールしてしまっており、それをtweet.pyから呼び出そうとしてしまってたので、
モジュールオブジェクトを関数的(class.tweet(message)的)に呼び出すことは出来ないぜ!というエラーでした。Twitterどうのこうのではなく、私のスキル不足な話です。
なので、Classの方でreturnでツイートするようにし、tweet.pyから呼び出す時にtryしてエラーハンドリングするようにしました。

これも結構ハマった。

ModuleNotFoundError: No module named ‘twitter’

これは、import twitterをしてる部分で「twitter」という部品が見つからないからimportできないぜってエラーです。

こういう時はまず

$ which twitter

と唱えてモジュールの在処を探す。
結果「 /usr/local/bin/twitter 」にあるらしい。

次にLinuxの環境変数を確認してみる。

$ echo $PATH

/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin

うーん。/usr/local/bin/は含まれているよなぁ。
Linuxじゃなくて、Pythonから呼び出せていないのか?

ということで次にPythonを対話式に開いて確認してみる。以下を実施

$ python3
>>>import sys
>>>print(sys.path)

[”, ‘/usr/lib/python37.zip’, ‘/usr/lib/python3.7’, ‘/usr/lib/python3.7/lib-dynload’, ‘/usr/local/lib/python3.7/dist-packages’, ‘/usr/lib/python3/dist-packages’]

おやおや。ここには居ないね。
ということで、
>>>sys.path.append(‘/usr/local/bin/twitter’)とするも解決せず。
しかも、このsys.path.appendは、この画面を抜けるとリセットされちゃうみたいで使い物にならず。

export PYTHONPATH=’追加したいPATH’

と唱えることで永続的になるんだけど、これでも解決せず。

いっそ、PATHの通ってるとこにモジュールを移動しちゃえ!とワケワカメにコピーコマンドを打ちまくっても解決せず。

結論:インストール方法が間違ってました。

Twitterモジュールをインストールする際、

$ sudo pip install twitter

と唱えた訳ですが、私のスクリプトはPython3で書いてテストしている訳なので、

$ sudo pip3 install twitter

と、唱えなきゃいけなかった訳ですよ。

これで、あっさり動いちゃったのです。
後で/usr/local/lib/python3.7/dist-packagesに移動しまくったモジュール達は気持ち悪いのでポチポチと消していきました。入れて出してバカみたいだ。

ともあれ、こんな感じでお勉強を進めています。

これからもしっかり技術を身につけ、何か面白いものを作ってみたいです。

最後までお読み頂き、ありがとうございました。