find100

日常の中で見つけた面白そうなことを発信します

MENU

Pythonでツイッターのbotを作ったときの話

僕はある日いつも通りツイッターをしながらこう思った。

よく見るbotってどうやって作っているのだろう?

それが動機でbotを自分で作ってみることにした。


※文体は特に統一しておらず、語尾に一貫性がないのでご了承ください。

まずは何を作るか
大学での専攻はバイオ系(生命科学系)なので少しはそこらへんの分野も取り入れられれば良いなと思ってランダムに仮想的なDNAを作成し、その仮想的なDNAをmRNAに変換してアミノ酸を合成しているかのようなbotを作ることにした。

botを作る際にはツイッターのルールに違反していないか下のサイトから確認しておきましょう。念の為。
help.twitter.com

botの作成方法について何にも知らなかったので軽く調べてみると大まかな流れとしては下の3つに分けられます。

1 keyを確認する
2 必要なモジュールをインストールし、実行したいコードを書く
3 自動実行する

先に言っておきますが、ツイッターbotを作るサービス(twittbotなど)を利用する人はこの記事を読む必要はありません。
そもそも1番の作業とかもやる必要ないですし。

ですからほぼ*1自力で作りたい人に読んでもらいたいです。

1番のkeyを確認するという過程は以下の記事を参照して下さい。
とても分かりやすかったです。
https://www.google.com/url?sa=t&rct=j&q=&esrc=s&source=web&cd=3&ved=2ahUKEwjG_-Pf7bXiAhUGMd4KHWWOBjcQFjACegQIBhAB&url=https%3A%2F%2Finfoma-info.com%2Fpython-twitter-0&usg=AOvVaw36BQnTyojnWVsO8EHcu_u5

次は2番です。Pythonツイッターをいじるには様々なモジュール がありますが僕はtweepyをインストールしました。
そして実際に完成した(完璧とは言っていない)コードがこちらです。

#coding: UTF-8
import tweepy
import random

CK = "XXX・・・X"
CS = "XXX・・・X"
AT = "XXX・・・X"
AS = "XXX・・・X"
auth = tweepy.OAuthHandler(CK,CS)
auth.set_access_token(AT,AS)

api = tweepy.API(auth)
dna = []
strings = ["A", "T", "G", "C"]
n = 140
k = 3
amino_acid = {"GCA":"Ala","GCC":"Ala", "GCG":"Ala", "GCU":"Ala",
"AGA":"Arg","AGG": "Arg", "CGA": "Arg", "CGC":"Arg", "CGG":"Arg", "CGU":"Arg",
"GAC":"Asp","GAU":"Asp",
"AAC":"Asn","AAU":"Asn",
"UGC":"Cys","UGU":"Cys",
"GAA":"Glu","GAG":"Glu",
"CAA":"Gln","CAG":"Gln",
"GGA":"Gly","GGC":"Gly","GGG":"Gly","GGU":"Gly",
"CAC":"His","CAU":"His",
"AUA":"ile","AUC":"ile","AUU":"ile",
"UUA":"Leu","UUG":"Leu","CUA":"Leu","CUC":"Leu","CUG":"Leu","CUU":"Leu",
"AAA":"Lys","AAG":"Lys",
"AUG":"Met",
"UUC":"Phe","UUU":"Phe",
"CCA":"Pro","CCC":"Pro","CCG":"Pro","CCU":"Pro",
"AGC":"Ser","AGU":"Ser","UCA":"Ser", "UCC":"Ser", "UCG":"Ser", "UCU":"Ser",
"ACA":"Thr","ACC":"Thr", "ACG":"Thr", "ACU":"Thr",
"UGG":"Trp",
"UAC":"Tyr","UAU":"Tyr",
"GUA":"Val","GUC":"Val", "GUG":"Val", "GUU":"Val",
"UAA":"","UAG":"","UGA":""}

#DNAからmRNAに変換します
def from_dna_to_mrna(Dna):
    mrna = Dna.translate(str.maketrans({"A": "U", "T": "A", "G": "C", "C": "G"}))
    if "AUG" in mrna:
        find_startcodon = mrna.find("AUG")
        mrna = mrna[find_startcodon:140]
    else:
        api.update_status("開始コドン(AUG)が見つかりませんでした")
    return mrna

#140字のランダムな仮想DNAを作ります
def random_dna():
    for i in range(140):
        nucleotide = random.choice(strings)
        dna.append(nucleotide)
    Dna = "".join(dna)
    return Dna

#mRNAからアミノ酸に翻訳します
def translate_amino_acid(mrna):
    amino_acid_strings = []
    l = len(mrna)
    if "AUG" in mrna:
        for i in range(0, l-k+1, 3):
            codon = mrna[i:i+k]
            amino_acid_strings.append(amino_acid[codon])
            if codon == "UAA" or codon == "UAG" or codon == "UGA":
                break
    Amino_acid_strings = "/".join(amino_acid_strings)
    return Amino_acid_strings

Random_dna = random_dna()
From_dna_to_mrna = from_dna_to_mrna(Random_dna)
api.update_status("DNA:{}".format(Random_dna))
api.update_status("mRNA:{}".format(From_dna_to_mrna))
api.update_status("アミノ酸:{}".format(translate_amino_acid(From_dna_to_mrna)))

ここで問題だったのはAtom(エディタ)上で実行しようとすると「Module Not Found Error」を吐かれてしまうことでした。

そこで実行したいコードの書かれたスクリプトで「print(sys.prefix)」を行うとAtom上で使われているのはグローバル環境にあるPythonだと分かりました。おそらくそれが原因で仮想環境内にあるPythonのTweepyが見つからなかったのだと思われます。
まぁターミナルで動くからいいやと思って無視しましたが。

TwitterAPIから得られた各種keyは伏せさせていただきます。
コードの出来としては微妙ですね。
amino_acidのところはタプルを使ってもう少しキレイに書けると良かったのですが・・・。

あと関数random_dna()ももっと簡潔に書いた方が良いのでしょうけど。
まぁ「Done is better than perfect.」なので(手抜きの理由に使うな)。

また、遺伝暗号はEssential細胞生物学第4版の239ページを参考にしています。
そしてDNAは二本鎖で転写の際はどちらの鎖が使われるか選ばれるらしいのですがそこは今回考慮していません。

で、最後の3番についてです。正直ここが一番時間かかったと言っても過言ではないです。
まず自動でスクリプトを実行するのに何使おうかと思って調べたらcrontabを使うのがオススメって出てきたので最初はそれを使おうと思ってたのですが、どうやらMacOSの場合はlaunchdが推奨されてることが判明したのでlaunchdを使うことにしました。

launchdの使い方については下のサイトを参考にして下さい。
下のサイトで紹介されている参考サイトも見るとより分かりやすいと思います。
https://www.google.com/url?sa=t&rct=j&q=&esrc=s&source=web&cd=1&ved=2ahUKEwjzzrf_nLbiAhUWH3AKHYKcBagQFjAAegQIABAB&url=http%3A%2F%2Fbanmian.hatenablog.com%2Fentry%2F2017%2F06%2F15%2F231344&usg=AOvVaw0Yo52ivR0ttmswA4ejBlW4

一応僕の書いたplistファイルも載せておきます。

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
  <!-- label -->
  <key>Label</key>
  <string>twitterbot.python</string>

  <!-- script -->
  <key>ProgramArguments</key>
  <array>
    <string>/Users/userDesktop/python_lesson/Twitter/venv/bin/python3</string>
    <string>/Users/user/Desktop/python_lesson/Twitter/venv/twitter_bot.py</string>
  </array>

  <!-- launchctl loadしたタイミングで実行するか -->
  <key>RunAtLoad</key>
  <true/>

  <!-- カレンダー指定 -->
  <key>StartCalendarInterval</key>
  <array>
  <dict>
     <key>Hour</key>
     <integer>0</integer>
     <key>Minute</key>
     <integer>0</integer>
  </dict>
  <dict>
     <key>Hour</key>
     <integer>6</integer>
     <key>Minute</key>
     <integer>0</integer>
  </dict>
  <dict>
     <key>Hour</key>
     <integer>12</integer>
     <key>Minute</key>
     <integer>0</integer>
  </dict>
  <dict>
     <key>Hour</key>
     <integer>18</integer>
     <key>Minute</key>
     <integer>0</integer>
  </dict>
  </array>



  <!-- ログの指定 -->
  <key>StandardErrorPath</key>
  <string>/Users/username/Desktop/python_lesson/Twitter/venv/err.log</string>
  <key>StandardOutPath</key>
  <string>/Users/username/Desktop/python_lesson/Twitter/venv/log.log</string>

</dict>
</plist>

plistファイルに問題があるか確認したい場合はターミナルから
「plutil XXX.plist」(XXXの部分は自分が作ったファイル名に書き換えて下さい)を実行すると確認できます。
このbot作成を機に仮想環境を初めて作ったので良かったなと。

あと当たり前かもしれないですけど仮想環境内で実行したいファイルを作ったなら仮想環境内に入ってからlaunchdコマンドで登録しないといけません。

仮想環境の外で登録するとエラーが出ます。

なんだかんだこのbotを作るのに3週間ぐらいかかりましたが、正常に動いてくれたときはめっちゃ嬉しかったです。

興味のある方は是非見て下さい。
twitter.com

*1:モジュールとか使ってる時点で自力じゃないやんとかいう意見はスルーします