こんにちは。RockinWoolです。
前回の記事で挑戦したように、今日はTwitterの情報を入手して遊ぶプログラムを作っていこうと思います。
ただし、今回のプログラムは個人情報の多いものとなっているのですべてを公開することは難しいです。ご了承ください。
さて、前回はおそらくTwitterAPIのアカウント登録をして4つの鍵を手に入れたところで終わっているのだと思います。
ということで、これからそれをプログラムに読ませて活用していこうと思います。

まず、前回pandasを使用してデータを保存すると言ったがあれは嘘だ。
pandasを使用するとdive_search関数(この記事の作者が名付けたものかな?)の再起処理の部分で引っかかってしまいうまく行かない。
そこで多少重くなるがpythonのcsvライブラリを使って処理中にcsvファイルに書き込んでもらう形に変更した。
具体的にメイン部分は次のようにまとめられる\

with open('data.csv', 'w') as f:
    writer = csv.writer(f)
    dive_search(targets, 0,writer)

もともとがかなり整ったプログラムなので実質的には前に二行足しただけである。
こんな書き方は良くないとかあったらぜひ指導してください。
とりあえず解説すると、dive_serch関数は再起関数で引数に指定した人のフォロワーのリストと深さdを持っています。
最初の実行で起点となる友人のリストが用意されて、その処理の途中で友人のリストの上から順に再び友人のリストが用意されて・・・というものの繰り返しで深さ分のフォロワー情報を入手することができます。
弱点はtwitterAPIが15リクエスト/15分という制約をかけているということです。
したがって今日は作成したプログラムを回しながら帰宅することにしようと思います。
明日はさっきの記事の後半部分。自分の専門分野であるネットワークについて実践していこうと思います。
今日の記事で作成したプログラムは↓にあげておきます。コメントいただけると嬉しいです(ほとんど丸パクリだけど)
それではここまで読んでくださってありがとうございました

import json
from requests_oauthlib import OAuth1Session
from time import sleep
import datetime
import Twitconf as tc
import pandas as pd
import csv

# APIキー設定(別ファイルのconfig.pyで定義しています)
Keys = tc.twconf()
# 認証処理
twitter = OAuth1Session(Keys.APIK,Keys.APISK,Keys.ACT,Keys.ACTS)
#情報収集
get_friends_url = "https://api.twitter.com/1.1/friends/list.json" # フォローしているアカウントを取得
get_user_info_url = "https://api.twitter.com/1.1/users/show.json" # ユーザー情報を取得する
count = 200
targets = ['任意のフォロワーを入れてね']
registed_list = []
depth = 2# 潜る深さ
max_friends_count = 1000 # フォローアカウントがめちゃくちゃ多い人が居るので一定数を超えてると除外する

# フォローアカウントが一定数を超えていないか判定する
def judge_friends_count(screen_name):
    params = {'screen_name': screen_name}
    while True:
        res = twitter.get(get_user_info_url, params=params)
        result_json = json.loads(res.text)
        if res.status_code == 200:
            # フォローしている人数は「friends_count」、フォローされている人数は「followers_count」
            if result_json['friends_count'] > max_friends_count:
                return False
            else:
                return True
        elif res.status_code == 429:
            # 15分間で15回しかリクエストを送信出来ないので上限に達していたら待つ
            now = datetime.datetime.now()
            print(now.strftime("%Y/%m/%d %H:%M:%S") + ' 接続上限のため待機')
            sleep(15 * 65) # 15分待機
        else:
            return False

# 指定したscreen_nameのフォロワーを取得する
def get_followers_info(screen_name):
    followers_info = []
    params = {'count': count,'screen_name': screen_name}
    while True:
        res = twitter.get(get_friends_url, params=params)
        result_json = json.loads(res.text)

        if res.status_code == 200 and len(result_json['users']) != 0:
                for user in result_json['users']:
                    # APIから取得した情報のうち、必要な情報だけをdict形式で設定 (このPGでidは使ってない・・)
                    followers_info.append({'screen_name': user['screen_name'], 'id': user['id']})
                # パラメーターに次の取得位置を設定する
                params['cursor'] = result_json['next_cursor']
        # APIの接続上限を超えた場合の処理           
        elif res.status_code == 429:
            now = datetime.datetime.now()
            print(now.strftime("%Y/%m/%d %H:%M:%S") + ' 接続上限のため待機')
            sleep(15 * 60) # 1分待機
        else:
            break
    return followers_info

# dictのlistからscreen_nameのみのlistを取得する
def followers_list(followers_info):
    followers_list = []
    for follower in followers_info:
        followers_list.append(follower['screen_name'])
    return followers_list

# 再帰処理
def dive_search(target_list, d,writer):
    for name in target_list:
        if name in registed_list or not judge_friends_count(name):
            continue
        print(name)
        writer.writerow([d,name])
        followers_info = get_followers_info(name)
        registed_list.append(name)
        if depth > d:
            dive_search(followers_list(followers_info), d + 1,writer)
        else:
            return

with open('data.csv', 'w') as f:
    writer = csv.writer(f)
    dive_search(targets, 0,writer)

Leave a Reply

Your email address will not be published. Required fields are marked *