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

Bre*_*ier 5 twitter parallel-processing r

有没有办法阻止我的循环被速率限制中断?如果可能的话,我希望我的代码等到时间限制过后才执行。

一个附带问题:我考虑过并行化 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)}
       )

}
Run Code Online (Sandbox Code Playgroud)

Sas*_*sha 5

我能够通过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)
}
Run Code Online (Sandbox Code Playgroud)


Bre*_*ier 2

我最终做的是创建一个 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)
Run Code Online (Sandbox Code Playgroud)