PRAWで遊ぶ(Python Reddit API Wrapper)

ここではPRAWでredditの投稿(submission)を取得する。さしあたりread_only=Trueで済むことだけをやっていく。知見が溜まったらbotを作ってもいいかもしれない。

PRAWのドキュメントに載っている最小利用例を引く。(以下の認証情報は本物ではない。あなたが作るプログラムにはhttps://www.reddit.com/prefs/apps から自分でアプリを登録して得たclient_id, client_secretを使う)

reddit = praw.Reddit(client_id='SI8pN3DSbt0zor',
                     client_secret='xaxkj7HNh8kwg8e5t4m6KvSrbTI',
                     password='1guiwevlfo00esyy',
                     user_agent='testscript by /u/fakebot3',
                     username='fakebot3')

# /r/learnpython のホッテントリを10件取得
for submission in reddit.subreddit('learnpython').hot(limit=10):
    print(submission.title)

しかし、認証情報を直書きするのはよくない。ローカルで使う場合は問題ないが、このようなコードを、ブログやgithubなどに公開した場合、登録したアプリが乗っ取られて悪用される恐れが大きい。

コードから認証情報を分離するために、praw.iniファイルを使う。

プログラムが置かれているディレクトリにpraw.iniファイルを作り、重要な情報はそこに隔離しておく。以下のように(認証情報は自分のものに書き換えて)記述する。my_botの部分は自分の好きな名前を記述してよい。

[my_bot]
client_id     = SI8pN3DSbt0zor
client_secret = xaxkj7HNh8kwg8e5t4m6KvSrbTI
username      = 1guiwevlfo00esyy
password      = fakebot3 

これを作っておくとprawの初期化が楽になる。

reddit = praw.Reddit('my_bot',
                     user_agent='my cool user agent')

以上の初期化を前提として、redditオブジェクトを実際に使っていく。

試しに/r/Pythonの24時間以内の投稿をスコアの高い順に表示してみる。

subreddit = reddit.subreddit('Python')
print(f'/r/{subreddit.display_name}')

for submission in subreddit.top('day'):
    print(f'{submission.title} [{submission.score}]')
    print(submission.url)

この日はipython 6.0のリリースがトップだった。

続いて/r/Animeのsubmissionから[Fanart] flairを抽出してみる。

import re

subreddit = reddit.subreddit('Anime')
print(f'/r/{subreddit.display_name}')

for submission in subreddit.top('day', limit=100):
    if re.search(r'\[Fanart\]', submission.title):
        print(f'[{submission.score}] {submission.title}')
        print(submission.url)

/r/Animeのポストは、selfの本文に画像リンクが貼ってあることが多い。また画像アップローダーにimgurがよく使われる。

そこで、上のコードを変更し、selftextからimgurのリンクだけ抽出するコードを書いてみる。

for submission in subreddit.top('day', limit=100):
    if re.search(r'\[Fanart\]', submission.title):
        pattern = r'imgur\.com/(gallery/|a/|)[a-zA-Z\d\.]+'
        matches = re.finditer(pattern, submission.selftext)
        if matches:
            for m in matches:
                print(f'http://{m.group()}')

正規表現がズボラですが、selftextとにらめっこした限り一応抽出できているようなのでこれでよしとしましょう。)

ここまで来ると/r/Animeに投稿されたFanart画像を収集するbotが作れそうですね。/r/Anime/に限らず2次画像が投稿されるsubrreditは多く存在する(NSFWも多い)ようなので、そこらへんのサブレも含めるといいかもしれない。

などと妄想がすこし膨らんだが飽きたので今日はここまで。