使用rtweet get_timeline()避免速率限制

时间:2017-02-03 13:59:32

标签: r twitter parallel-processing

无论如何都要阻止我的循环被速率限制打断?我希望我的代码等待执行,直到时间限制已经过去。

一个附带问题:我考虑过并行化for循环。你认为这会是一个好主意吗?我不确定是否有可能将数据写入错误的文件。

library(rtweet)
create_token(app="Arconic Influential Followers",consumer_key,consumer_secret) 

flw <- get_followers("arconic")
fds <- get_friends("arconic")
usrs <- lookup_users(c(flw$user_id, fds$user_id))

for(i in 1:length(usrs$user_id)){

    a<-tryCatch({get_timeline(usrs$user_id[i])},
                error=function(e){message(e)}
       )
    tryCatch({save_as_csv(a,usrs$user_id[i])},
                error=function(e){message(e)}
       )

}

2 个答案:

答案 0 :(得分:1)

我最终做的是创建一个while循环,检查我在Users向量中留下的记录数,运行for循环,然后让系统进入睡眠状态15分钟。这种方法很好,但有一些事情需要考虑。我将while循环打破200,以防万一有用户没有任何数据保存到csv中。事实证明这是一个很好的举措,因为如果你注意到for循环开始迭代80.当你开始在你的用户向量中移动时,好的用户会被迭代删除。这只留下导致错误的用户。对于完成任务的人来说,改进就是以编程方式处理这个问题。

Users <- usrs$user_id
goodUsers <- substring(list.files(),1,nchar(list.files())-11)
Users <- setdiff(Users,goodUsers)

while(length(Users)>200){
    for(i in 80:length(Users)){

        a<-tryCatch({get_timeline(Users[i],usr=FALSE)},
                error=function(e){message(e)}
           )
        tryCatch({save_as_csv(a,Users[i])
                goodUsers <- append(goodUsers,Users[i])},
                    error=function(e){message(e)}
        )


    }
Users <- setdiff(Users,goodUsers)
Sys.sleep(900)
}

length(Users)
length(goodUsers)

答案 1 :(得分:0)

我可以通过将get_timeline()函数包装在以下代码中来解决该问题。 get_timeline_unlimited函数在等待所需时间以重置速率限制后递归调用自身。到目前为止,它对我来说没有任何问题。

 get_timeline_unlimited <- function(users, n){

  if (length(users) ==0){
    return(NULL)
  }

  rl <- rate_limit(query = "get_timeline")

  if (length(users) <= rl$remaining){
    print(glue("Getting data for {length(users)} users"))
    tweets <- get_timeline(users, n, check = FALSE)  
  }else{

    if (rl$remaining > 0){
      users_first <- users[1:rl$remaining]
      users_rest <- users[-(1:rl$remaining)]
      print(glue("Getting data for {length(users_first)} users"))
      tweets_first <- get_timeline(users_first, n, check = FALSE)
      rl <- rate_limit(query = "get_timeline")
    }else{
      tweets_first <- NULL
      users_rest <- users
    }
    wait <- rl$reset + 0.1
    print(glue("Waiting for {round(wait,2)} minutes"))
    Sys.sleep(wait * 60)

    tweets_rest <- get_timeline_unlimited(users_rest, n)  
    tweets <- bind_rows(tweets_first, tweets_rest)
  }
  return(tweets)
}