twitter管理アプリのmock作成

· ☕ 3

ついに作り始めました。

設計はこちら

システム構成図

こんな感じで作っていきます。

dynamoDBのtable作成

dyanmoDB作成チートシートに従って作成。

1
2
3
4
5
6
7
8
cd /mnt/c/github/runau/work
table_name=twitter_follower
env=dev
param='Env=$env TableName=$table_name HashKey=id'
#↑を書き換える
template_name='dynamo'
stack_name='$template_name-`echo $table_name | sed s/_/-/`-$env'
aws cloudformation deploy --template-file ./template-$template_name.yaml --stack-name $stack_name --parameter-overrides $param

lambdaの元になるpython作成

まずは、

  • 自分がフォローしている人全員を取得

  • 自分のフォロワーを全員を取得

  • 上記をマージ

  • dynamoDBに保存

  • ↑で保存したdynamoDBフルスキャン

を試しに作っていきます。

dynamoは結構な更新量になるので、今回はプロビショニニングの無料枠を使っています。

フルスキャンをやめるとか、パフォーマンスや節約的な部分は後々考えます。

自分がフォローしている人全員を取得

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
from requests_oauthlib import OAuth1Session, OAuth1
import requests
import json
import boto3
import os

OAUTH1 = os.environ['OAUTH1']
OAUTH2 = os.environ['OAUTH2']
OAUTH3 = os.environ['OAUTH3']
OAUTH4 = os.environ['OAUTH4']
TWITTER_ID = os.environ['TWIITER_ID']

def getOauth():
    return OAuth1(OAUTH1, OAUTH2, OAUTH3, OAUTH4)


def getFriendsIds(userId):
    res = requests.get(
        f'https://api.twitter.com/1.1/friends/ids.json?user_id={userId}',
        auth=getOauth()
    ).json()
    if 'errors' in res:
        print(res)
        raise RuntimeError(res)

    nextCursor = res['next_cursor']

    while nextCursor != 0:
        tmpRes = requests.get(
            f'https://api.twitter.com/1.1/friends/ids.json?user_id={userId}&cursor={nextCursor}',
            auth=getOauth()
        ).json()
        if 'errors' in tmpRes:
            print(tmpRes)
            raise RuntimeError(tmpRes)
        res['ids'] += tmpRes['ids']
        nextCursor = tmpRes['next_cursor']
        break

    return res['ids']

print(getFriendsIds(TWITTER_ID))

実行結果

[87648556, 1896561458, 713630842799661056, 595534764, 729111324018368512, 279596610, 168542837, 4364868434, 389825876, 831543164729167873, 3349941013, 3034835300, 1044459784810819589, 1053559069473103872, 1054582649350569989, 1078538179106430976, 840859268089757696, 1102897036708311045
~略~

自分のフォロワーを全員を取得

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
from requests_oauthlib import OAuth1Session, OAuth1
import requests
import json
import boto3
import os

OAUTH1 = os.environ['OAUTH1']
OAUTH2 = os.environ['OAUTH2']
OAUTH3 = os.environ['OAUTH3']
OAUTH4 = os.environ['OAUTH4']
TWITTER_ID = os.environ['TWIITER_ID']

def getOauth():
    return OAuth1(OAUTH1, OAUTH2, OAUTH3, OAUTH4)


def getFollowersIds(userId):
    res = requests.get(
        f'https://api.twitter.com/1.1/followers/ids.json?user_id={userId}',
        auth=getOauth()
    ).json()
    if 'errors' in res:
        print(res)
        raise RuntimeError(res)

    nextCursor = res['next_cursor']

    while nextCursor != 0:
        tmpRes = requests.get(
            f'https://api.twitter.com/1.1/followers/ids.json?user_id={userId}&cursor={nextCursor}',
            auth=getOauth()
        ).json()
        if 'errors' in tmpRes:
            print(tmpRes)
            raise RuntimeError(tmpRes)
        res['ids'] += tmpRes['ids']
        nextCursor = tmpRes['next_cursor']
        break

    return res['ids']

print(getFollowersIds(TWITTER_ID))

実行結果

[87648556, 1896561458, 713630842799661056, 595534764, 729111324018368512, 279596610, 168542837, 4364868434, 389825876, 831543164729167873, 3349941013, 3034835300, 1044459784810819589, 1053559069473103872, 1054582649350569989, 1078538179106430976, 840859268089757696, 1102897036708311045
~略~

上記をマージ

1
2
3
4
5
6
7
friendsIds = getFriendsIds(TWITTER_ID)
followersIds = getFollowersIds(TWITTER_ID)

users = dict(map(lambda x:(x,{'follow': False, 'followed': False}),friendsIds+followersIds))
[users[id].update({'follow' : True}) for id in friendsIds]
[users[id].update({'followed' : True}) for id in followersIds]
print(users)

実行結果

{ 865995172735102976:{'id': 865995172735102976, 'follow': True, 'followed': True}, 1057977058062553089: {'id': 1057977058062553089, 'follow': True, 'followed': True}, 1098072707910922241: {'id': 1098072707910922241, 'follow': True, 'followed': True}, 950362254993629184: {'id': 950362254993629184, 'follow': True, 'followed': True}
~略~

dynamoDBに保存

1
2
3
4
dynamoDB = boto3.resource('dynamodb')
table = dynamoDB.Table('twitter_follower_dev')

[table.put_item(Item=val) for val in users.values()]

実行結果

dyanmo

↑で保存したdynamoDBフルスキャン

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
import boto3

def scanDynamo(tableName):
    dynamodb = boto3.resource('dynamodb')
    dynamodb_table = dynamodb.Table(tableName)
    response = dynamodb_table.scan()
    data = response['Items']
    while 'LastEvaluatedKey' in response:
        response = dynamodb_table.scan(ExclusiveStartKey=response['LastEvaluatedKey'])
        data.extend(response['Items'])

    return data

print(scanDynamo('twitter_follower_dev'))

実行結果

[{'followed': True, 'id': Decimal('1088004537607061504'), 'follow': True}, {'followed': True, 'id': Decimal('1098844933501345792'), 'follow': True}, {'followed': True, 'id': Decimal('1137340823815647232'), 'follow': True}, {'followed': True, 'id': Decimal('541802366'), 'follow': True}, {'followed': True, 'id': Decimal('1084794730590875648'), 'follow': True}
~略~

独り言

いい感じ//

後は、ここに日付的情報を追加して、lambdaにまとめて、各ユーザーの情報を追記していくlambdaをもう一個作れば完成//

とりあえず、FF比が9割になりかけていたので、↑のdynamoからフォローしているけど、フォローされていないユーザーを200人くらいゆっくりフォロー解除してみました。

これができるだけでも、このツール作った意味があるww

FF比復活!

FF比復活!


るな
るな
エンジニア