无论如何都要阻止我的循环被速率限制打断?我希望我的代码等待执行,直到时间限制已经过去。
一个附带问题:我考虑过并行化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)}
)
}
答案 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)
}