機略戦記

Maneuver warfare

異なるディレクトリに入った同名のファイルを1箇所にまとめたい

  • 異なるディレクトリに入った同名のファイルを1箇所にまとめたい。
  • ファイル名が同一なので、何かユニークな名前に変える必要がある。

結論

for i in `find . | grep .gz`
do
  before=$i
  after=`echo $before | sed 's/\.\///g' | sed 's/\//_/g'`
  `cp $before $after`
done

こんな感じ。

説明

こんな感じだとする。

find .
$ find . -type file
./dirctory_01/a.gz
./dirctory_02/a.gz
./dirctory_03/a.gz

上記のファイルがこうなる。

./dirctory_01_a.gz
./dirctory_02_a.gz
./dirctory_03_a.gz

例えば`find .`の結果に対して繰り返し同じ処理を適用したい

あるコマンドの実行結果として得られたすべての行に対して別の処理を行いたい。
例えばfind .の結果に対して繰り返し同じ処理を適用したい。

結論

for line in `find .` ; do ; echo $line ; done

解説

  • find .の結果が変数$lineに格納される。
  • echo $linefind .の結果すべてに対して実行される。

使用例

カレントディレクトリ以下すべてのcsvファイルに対して何がしかの処理を行う。(ここではecho

for line in `find . | grep .csv` ; do ; echo $line ; done

Twitter APIを制限目一杯まで実行したい

結論

  • あるAPIを残り何回叩けるか、いつ制限がリセットされるかなどの情報を取得できるTwitter APIがあるので、そいつから取得した情報を元に制限一杯まで実行すれば良い。

このAPI:

dev.twitter.com

背景

やりたい事

  • あるTwitterアカウントをフォローしているユーザーその他にどんなアカウントをフォローしているのかを調べたい。

最初に試した方法

  • あるTwitterアカウントをフォローしているユーザーを取得したのち、それぞれのユーザーに対してフォローしているアカウントの一覧を取ろうとした。
  • ruby gemのにTwitter APIをいい感じにラップしてくれるやつがあったので、それを使った。

github.com

最初に試した方法の課題点

  • あるTwitterカウントのフォロワー数分APIを叩く事になる。
  • twitter APIには非常に厳しい実行回数制限がある。
  • 実行回数の制限に引っかかると、例外を吐いてプログラムが終了するので全然はかどらない。

参考:

Rate Limits: Chart | Twitter Developers

対策

  • あるAPIを残り何回叩けるか、いつ制限がリセットされるかなどの情報を取得できるTwitter APIがあるので、そいつから取得した情報を元に制限一杯まで実行する。

実装

require 'twitter'

# API制限を表現するクラス
class APILimitStatus
  def initialize(client, target_end_point, target_api)
    @client = client
    @target_end_point = target_end_point
    @target_api = target_api

    setup_or_update_limit_status!
    check_arguments!
  end

  # もし制限に達していたら制限がリセットされるまでスリープする。
  def sleep_to_reset_if_limit!
    setup_or_update_limit_status!

    if remaining <= 0
      sleep(need_seconds_for_reset)
    end
  end

  private

  # 次回制限リセットまでの残り秒数
  def need_seconds_for_reset
    now = Time.now.to_i
    (reset_at - now) > 0 ? (reset_at - now) : 0
  end

  # 残り実行回数リセット時刻
  def reset_at
    @limit_status[@target_end_point][@target_api][:reset]
  end

  # 残り実行可能回数
  def remaining
    @limit_status[@target_end_point][@target_api][:remaining]
  end

  # limit_statusをupdateする。なければsetupする。
  def setup_or_update_limit_status!
    limit_status = @client.__send__(:perform_get, '/1.1/application/rate_limit_status.json')
    @limit_status = limit_status[:resources]
  end

  # 制限を調べたいAPIの指定が間違っていたら雑な例外を出す。
  def check_arguments!
    raise if @limit_status[@target_end_point].nil?
    raise if @limit_status[@target_end_point][@target_api].nil?
  end
end

# 設定
client = Twitter::REST::Client.new do |config|
  config.consumer_key        = ""
  config.consumer_secret     = ""
  config.access_token        = ""
  config.access_token_secret = ""
end

SURVEY_USER_ID = "hoge"

# あるidをフォローしているユーザーの一覧
follower_api_limit = APILimitStatus.new(client, :followers, :"/followers/ids")
follower_api_limit.sleep_to_reset_if_limit!

follower_ids = client.follower_ids(user_id: SURVEY_USER_ID).attrs[:ids]

# ランダムな順番に並び替える。
# これなら一定数のfollower分のfriendが取得できた時点でサンプリングされたデータとして扱える
follower_ids.shuffle!

# あるidをフォローしているユーザーがフォローしているユーザーの取得
friend_api_limit = APILimitStatus.new(client, :friends, :"/friends/ids")

follower_ids.each do |follower_id|
  friend_api_limit.sleep_to_reset_if_limit!

  begin
    friend_ids = client.friend_ids(user_id: follower_id).attrs[:ids]
    puts "#{follower_id},#{friend_ids.to_s}"

  rescue Twitter::Error => e # 鍵アカとかも例外になるので。
    puts "#{follower_id},#{e.to_s}"
  end
end

twitter gemで、screen_nameではなくuser_idを指定してfollower_idsを取得したい

結論

client.follower_ids(user_id: SURVEY_USER_ID).to_a

ちなみにscreen_nameで指定する場合はこう

client.follower_ids(SURVEY_USER_SCREEN_NAME).to_a

説明

ここを読んだら分かった。

twitter/friends_and_followers.rb at b299925d22d9ccf75c50328cea34e3f0194e1a33 · sferik/twitter · GitHub

Github内をメソッド名で検索して辿り着いた。

twitter APIをrubyから実行したい

結論

  • twitter gem使おう

github.com

補足

  • twitter gemを使うのにあたって、各種認証情報が必要だ。
  • 認証情報を得るにはTwitterAppを作る必要がある(ようだ)。
  • tiwtterAppを作るには、地震のtwitterアカウントに電話番号を登録しておく必要がある。

参考

  • twitterAppを作る場所

https://apps.twitter.com/app/new

  • twitterに電話番号を登録する support.twitter.com

サンプルコード

lo-upe.hatenablog.com

この辺りがシンプルで参考になった。あとは、twitter gemのコードを読む。