徒然なるままな想い書き

日々の『思わぬ発見、気付き』をつれづれに。

【Raspberry Pi 2】ブログ記事をランダムTweetするBotをPythonとcronでつくる!

Raspberry P 2iでの遊びにも慣れてきた今日このごろ。

今回はラズパイを使ってこのブログの過去記事をランダムに選んで紹介するTweetのBotをつくってみたいと思います。

 

 

 

概要

今回使用するのは、

  • ラズパイ
  • Python
  • XML
  • cron

です。

 

おおまかに言うと、

  1. Pythonを使い、ブログのsitemapからXMLを取得して記事をランダムに抽出
  2. Twythonを使い、ランダムに記事をTweetする
  3. ラズパイ or レンタルサーバのcronにPythonスクリプトの実行を登録し、Tweetを自動化する

という流れでやっていきます。ラズパイを使いますが、自宅サーバやレンタルサーバとかでも同様にやればできるはずです。

 

1.ブログのsitemapからXMLを取得

このブログを例に扱います。このブログははてなブログですが、はてなブログではURL+sitemap.xmlでサイトマップを見られます。このブログだと、

http://tsurzur.hatenablog.com/sitemap.xml

です。このsitemap.xmlは入れ子構造になっていて、sitemap.xml?page=*が各記事のリンクを含む実体です。

 

このsitemapのXMLから各記事のリンクを、Pythonを使って取得します。

スクリプトはこんな感じです。

(xml_parser.py)

#!/usr/bin/env python
# coding: utf-8
 
from xml.dom import minidom
import random
import urllib2

def get_article(url):
    # list for blog articles
    list_article = []
    list_xml = []

    # sitemap.xmlを取得する
    #wget.download(url+"/sitemap.xml")
    sitemap_xml = urllib2.urlopen(url+"/sitemap.xml").read()
    # sitemap.xmlを読み込む
    file_xml = minidom.parseString(sitemap_xml)
    # sitemap.xmlの中からをすべて取得する(sitemapの全ページを取得する)
    pages_xmls = file_xml.getElementsByTagName("loc")

    # sitemapの全ページから、全記事を取得する
    for i, page in enumerate(pages_xmls) :
        # ページごとのxmlを取得する
        sitemap_xml = urllib2.urlopen(page.childNodes[0].data).read()
        # ページごとのxmlを読み込む
        file_xml = minidom.parseString(sitemap_xml)
        # xml内の全記事のurlを取得する)
        pages_xml = file_xml.getElementsByTagName("loc")
        # 各記事をlist_articleに格納していく
        for j, article in enumerate(pages_xml) :
            list_article.append(article.childNodes[0].data)

    # list_articleの中からランダムに一つ選択
    return random.choice(list_article)

スクリプトは以下のサイトを参考にさせていただきました。

Python で XML 操作 | TM Life

Python スクリプト実行時に UnicodeDecodeError が出る場合の対処方法 - Over&Out その後

 

 

コメントアウト部分に説明を載せています。ポイントとしては、

  • XMLの取得はulib2モジュールを使う
  • XMLの解析はminidomモジュールを使う
  • sitemap.xmlとsitemap.xml?page=*は入れ子構造なので、FOR文を回して記事リンク部分<loc>をすべてリストに格納
  • 記事リンクの入ったリストから、randomモジュールを使ってランダムに一つ記事リンクを抽出

です。この関数get_article()を使うことで、ブログのURLからランダムに記事を一つ抽出します。

 

2.Twythonを使って選んだ記事をTweetする

次はTweet部分です。スクリプトはこんな感じです。

(tweet_article.py)

#!/usr/bin/env python
# coding: utf-8

import sys
import os
import random
import xml_parser
from twython import Twython

if __name__ == "__main__":
    param = sys.argv

    # twitterの認証情報を入力
    CONSUMER_KEY = "***"
    CONSUMER_SECRET = "***"
    ACCESS_KEY = "***"
    ACCESS_SECRET = "***"
    api = Twython(CONSUMER_KEY,CONSUMER_SECRET,ACCESS_KEY,ACCESS_SECRET)

    # xml_parserのget_articleで取得した記事についてTweetする
    url = param[1]
    num_tweet = int(param[2])
    probability = random.randint(1,54)
    if probability <= num_tweet:
        comment = "私の書いているブログからのピックアップ記事です! "
        api.update_status(status= comment + xml_parser.get_article(url))

スクリプトは以下のサイトを参考にさせていただきました。

Raspberry PiのCPU温度をつぶやくTwitterBot | そう いう わけさ

 

 

こちらもコメントアウト部分に説明を載せています。ポイントとしては、

  • Twythonはpip install twythonで追加インストール
  • TwitterのAPIを使えるようにディベロッパーとして登録 -> Twitter Application Management
  • 登録情報をTwythonに渡すとTweetできる(関数update())ので、関数get_article()で得た記事についてTweet
  • cronで呼び出した時に、指定確率でしかTweetしないようにする(ランダム性を持たせる)

 

後のcronの設定との兼ね合いもありますが、probabilityの設定については自分がTweetさせたい条件に応じて自由にカスタマイズしてもらっても構いません。

 

スクリプトができたら、cron用に実行権限を付与しておきます。

sudo chmod +x tweet_article.py get_article.py

 

また、日本語を含むスクリプトをラズパイで実行すると、asciiが何とかかんとかと言われてエラーになるので、pythonのデフォルトエンコードをutf-8にする必要があります。なので、

/usr/lib/python2.7/sitecustomize.py

を編集して、

import sys
sys.setdefaultencoding('utf-8')

を追加しておいてください。

 

3.cronにスクリプト実行を登録してTweetをBotにする

最後にcronの登録です。cronの概要、設定については

cron の設定ガイド

などを参考してください。

 

はじめに、

crontab -e

でcronの編集画面を開きます。

その後、

*/20 6-23 * * * python /path/to/tweet_article.py your_url num_tweet

とし、cronでPythonスクリプトを指定時間で自動実行させるようにします。ここでは、6時から23時の間に20分間隔で指定パスにあるtweet_article.pyを実行させるようにしています。先ほどのtweet_article.pyでは呼び出されたとしても引数で渡す数字で決めた確率でしかTweetしないようにしており、これによってTweetにランダム性を持たせています。

 

 

感想

今回は自分のブログ記事のTweetでしたが、今回の方法を応用するといろんなBotが作れそうです。いい武器を身につけられた感じがしてます。

 

 

ではでは。