はてなブログの記事を自動生成して投稿するスクリプトを作りました。
はてなブログには、記事をスクリプトで投稿するAPIとMailによる投稿ができる仕組みがあります。
これを利用してTwitterの人気投稿を収集してブログ記事を生成します。
できあがったブログは↓。
この中で、Twitterの投稿をカード形式で埋め込みたかったのですが、APIではhtmlがエスケープされているようで目的が達成できません。
そこで、Mailによる投稿のスクリプトを作りました。
※人気Tweet選別の細かい仕様はノウハウとして、コードの中ではぼかしてあります。
全体の構成
Twiiterの投稿の取得は Tweepyを使用しています。
夜中の0時過ぎに自動的に起動して、以下のmain()が呼ばれると、
・Twiiter apiのauth認証
・人気Tweetの検索
・人気Tweetが不足していたら、自分のTweetから検索して追加
・Mailによるはてなブログ投稿
というながれです。
def main(): now = datetime.now() if now.day % 2 != 0: acount = "s" print("s51517765 Make blog!") api = login(acount) #twitter api tweet_list = search_tweet(api, acount) tweet_list = my_tweet(api, tweet_list) post_main(acount, tweet_list)
Twitter auth認証
def login(acount): if acount == "s": CONSUMER_KEY = "****************" CONSUMER_SECRET = "****************" ACCESS_TOKEN = "****************" ACCESS_SECRET ="****************" else: exit() #アカウント指定を確認して違っていれば終了 auth = tweepy.OAuthHandler(CONSUMER_KEY, CONSUMER_SECRET) auth.set_access_token(ACCESS_TOKEN, ACCESS_SECRET) api = tweepy.API(auth) return api
Twitterの検索
Twitter APIの検索に投げるキーワードはListで保持してRTやFav.で人気Tweetを検索します。APIではRTされているものは、RTごとに拾われるので中身を確認して重複しているものは除外します。
def search_tweet(api, acount, count=200): tweet_list = [] tweet_id = [] now = dt.today() if acount != "s": print("Acount Error") random.shuffle(keywordlist) #Twiiter検索につかうキーワード replypattern = r"@[\w]+" # 重複確認用 keyword_count = 0 for keyword in keywordlist: for tweet in api.search(q=keyword, count=count): # 検索 try: if tweet.retweet_count > ** or tweet.favorite_count > **): #人気記事の判定 if (now - tweet.created_at).days < 3: txt = tweet.text if txt.count("#") < 4: #ハッシュタグの多いTweetは除外 if is_japanese(txt): #日本語のTweet以外は除外 txt = re.sub(replypattern, '', txt) #@ や RT を除外する txt = txt.replace("RT", "") txt = txt.replace(":", "") txt = txt.replace(" ", "") if txt not in tweet_list: # RTによる重複確認 tweet_list.append(txt) tweet_id.append(tweet.id) else: break except: pass if len(tweet_id) > 40: break time.sleep(30) return tweet_id
自分の投稿は以下のようにして取得できます。自分がRTしたものは除きます。
Twiiter APIではRTはTweet本文status.text
にRT:
のようなテキストが付加されていますので、これを探します。
def my_tweet(api, tweet_list): for status in tweepy.Cursor(api.user_timeline).items(): if "RT" not in status.text : #自分がしたRTは除外 tweet_list.append(status.id) return tweet_list
日本語以外のTweetは除外します(日本語をキーワードに検索しているのになぜか全く関係ない海外のTweetが引っかかることがあるため)。
↓の記事を参考に、1文字でもひらがなorカタカナが含まれていれば日本語と判定します。
引用下では漢字を含めていますが、漢字はチェックしなくてもよいと考えました。
日本語で漢字のみで成立する文章というのは稀でかならず、ひらがなorカタカナが入ると思います。
minus9d.hatenablog.com
def is_japanese(string): for ch in string: name = unicodedata.name(ch) if "HIRAGANA" in name or "KATAKANA" in name: return True return False
投稿する本文
このスクリプトでMail投稿するときは「はてな記法」にする必要があります。Twiiterの投稿をカード形式で表示するために、
<a href=\"https://twitter.com/s51517765/status/************* "></a>
のようにTwitterのLinkをa
タグで挿入します。さらにこれをclass
で囲んでいます。
def post_main(acount, tweet_list): # はてな記法 now = datetime.today() yesterday = now - timedelta(days=1) title = "【" + str(yesterday.year) + "年" + str(yesterday.month) + "月" + str(yesterday.day) + "日" + "の人気ツイート】" body = "" for i in tweet_list: prefix = "<blockquote class=\"twitter-tweet\"><a href=\"https://twitter.com/s51517765/status/" sufix = "\"></a></blockquote><script async src=\"https://platform.twitter.com/widgets.js\" charset=\"utf-8\"></script>" body = body + prefix + str(i) + sufix + "\r\n" # メールによる投稿 # g_mail.send_mail(title, body, "*****************.draft@blog.hatena.ne.jp") # 下書き g_mail.send_mail(title, body, "*****************@blog.hatena.ne.jp") # 投稿
Mailによるはてなブログ投稿
投稿用のアドレスははてなブログの管理画面から取得します。↓を参考にスクリプトを作成します。G-mailは外部から制御できるように権限を開放する必要があります。
news.mynavi.jp
# gmail-py import smtplib, ssl from email.mime.text import MIMEText # https://news.mynavi.jp/article/zeropython-51/ # setting ----------------------------------------------------------- gmail_account = "********@gmail.com" gmail_password = "*********" # setting ----------------------------------------------------------- def send_mail(subject, body, mail_to="*******@gmail.com"): msg = MIMEText(body, "html") msg["Subject"] = subject msg["To"] = mail_to msg["From"] = gmail_account # Gmailに接続 --- (*4) server = smtplib.SMTP_SSL("smtp.gmail.com", 465, context=ssl.create_default_context()) server.login(gmail_account, gmail_password) server.send_message(msg) # メールの送信 print("Gmail send ok.")
まとめ
これで、ブログ記事を量産できます。ちなみにInstagramでも人気投稿を集めてブログ記事を作成というのを検討しているのですが、こちらはAPIで投稿を取得できなかったり、htmlが複雑だったりで考え中です。
参考
APIによる投稿tadaken3.hatenablog.jp
Tweepy
s51517765.hatenadiary.jp
s51517765.hatenadiary.jp
s51517765.hatenadiary.jp
自動投稿
karaage.hatenadiary.jp