如何在不达到 API 限制的情况下获得所有 Twitter 关注者

Posted

技术标签:

【中文标题】如何在不达到 API 限制的情况下获得所有 Twitter 关注者【英文标题】:How To Obtain All Twitter Followers Without Hitting API Limit 【发布时间】:2013-09-07 03:46:46 【问题描述】:

我想这很容易做到,但我不知道我做错了什么。我正在使用 Abraham 的 OAuth 来获得访问权限。我正在使用我的关注者信息构建一个数据库:屏幕名称、用户名和 Twitter ID。没什么特别的。

我参考了 Twitter 的“cursoring”页面,尤其是伪代码来编写我的代码。对于那些不想点击链接查看所述伪代码的人来说,它看起来像下面这样:

cursor = -1

api_path = "https://api.twitter.com/1.1/endpoint.json?screen_name=targetUser"

do 

    url_with_cursor = api_path + "&cursor=" + cursor      

    response_dictionary = perform_http_get_request_for_url( url_with_cursor )

    cursor = response_dictionary[ 'next_cursor' ]



while ( cursor != 0 )

对于每个请求,最终用户都会获得一个“光标”,允许他们浏览结果的“页面”。每页有 20 个,如果你有 200 个关注者,你必须浏览 10 页。我有超过 900 名追随者。我将其修改为如下所示:

 include('config.php');  //db connection
 include('twitter_oauth.php'); //oauth connection

 $followers = "";

$cursor = -1;
echo '<pre>';   
do 

    $consumerKey = 'xxx';
    $consumerSecret = 'xxx';
    $OAuthToken = 'xxx';
    $OAuthSecret = 'xxx';

    $tweet = new TwitterOAuth($consumerKey, $consumerSecret, $OAuthToken, $OAuthSecret);

    $followers = $tweet->get('followers/list', array('screen_name' => 'my_screen_name', 'cursor' => $cursor));

    print_r($followers);

    if (isset($followers->error)) 
        echo $followers->next_cursor_str;
        break;
     

    foreach($followers->users as $users) 

        $followersQ = mysql_query("SELECT * FROM followers WHERE tw_id = '".$users->id."'") or die(mysql_error());
        $num_rows = mysql_num_rows($followersQ);

        if ($num_rows == 0) 
            $followersQ2 = "INSERT INTO followers 
                                        (screen_name, name, tw_id)
                                        VALUES
                                        ('".$users->screen_name."', '".$users->name."', '".$users->id."')";
            $followersR = mysql_query($followersQ2) or die(mysql_error());
            echo 'done one set<br>';
        

    


    $cursor = $followers->next_cursor_str;



while ( $cursor != 0 );
echo '</pre>';

?>

以上代码调用 twitter 关注者/列表并获取前 20 个用户。然后它得到一个光标并转到下一个,然后重复。只是,似乎在大约 80 个用户之后它给了我可爱的感觉:

[errors] => Array
    (
        [0] => stdClass Object
            (
                [message] => Rate limit exceeded
                [code] => 88
            )

    )

我可以手动获取下一个光标,等待 15 分钟让速率限制下降,用光标再次调用该函数,获取接下来的 80 个项目,然后获取该键并重复,但我想设置一个可以一遍又一遍地调用它的脚本。

我觉得我做错了什么,要么是我调用 oAuth 的函数,要么是它之外的某个地方。有人能指出我正确的方向吗?

谢谢。

【问题讨论】:

您将需要限制您的速率,使用sleep(),您应该每 15 分钟有 15 个请求,这样您就可以在每个请求后休眠一分钟,或者先处理您的请求,然后再休眠 15 分钟.看起来还发送了标题信息以确定您何时可以再次访问dev.twitter.com/docs/rate-limiting/1.1 这不是一个坏主意。不过这需要几个小时。如果没有别的,我会这样做。谢谢! 【参考方案1】:

这种方式更快,但也存在限制问题:

1- 发出请求以获取所有关注者 id ...在页面中使用 5000 id 进行分页 https://developer.twitter.com/en/docs/twitter-api/v1/accounts-and-users/follow-search-get-users/api-reference/get-followers-ids

2- 在 id 上循环并以逗号分隔的字符串发送每 100 个 id 以获取他们的信息 https://developer.twitter.com/en/docs/twitter-api/v1/accounts-and-users/follow-search-get-users/api-reference/get-users-lookup

3- 现在你可以每 15 分钟获得 1500 个用户对象,而不是 300 个用户对象

但如果关注者列表超过 1500,您还需要每 15 个请求设置一个计时器

【讨论】:

我最终这样做了,但我将其修改为使用dev.twitter.com/docs/api/1.1/get/users/show,这样我就可以获得用户名和屏幕名称。你的概念效果很好,但我只需要更多数据。按照我的方法,我必须设置一个循环和一个计时器,就像 Relequestual 所说的那样,但最后它奏效了,所以谢谢你:) 欢迎您 :) ...不幸的是 twitter 限制太高,我们必须解决:D 我错过了什么吗?这不只是将瓶颈从第 1 步更改为第 2 步吗?已经有调用一次获取200个关注者,第2步一次是100个。 @pete 这个答案是 3 年前的,我真的不知道 twitter 是否更新了他们的 API 来解决这个问题。但这是 2013 年唯一的解决方案。 2017 年 - 用户/查找的限制为每 15 分钟 900 个,每个响应 100 个结果,每 15 分钟 90,000 个。现在的瓶颈是追随者/ID,每 15 分钟有 15 个请求,在 75,000 时返回 5,000 个 ID。【参考方案2】:

我认为没有任何方法可以绕过施加的限制。即使是 tweetbot 也有这个限制,因为这是 twitter 强加的限制。您可以在当前状态的数据库中创建一个注释,并将一个 cron 作业设置为每 15 分钟运行一次,这将再次运行一组请求。这需要时间,但完成后它会通过电子邮件通知您。这就是 socialbro 这样的服务所做的。当然,您会将这些结果缓存在您的数据库中。

【讨论】:

以上是关于如何在不达到 API 限制的情况下获得所有 Twitter 关注者的主要内容,如果未能解决你的问题,请参考以下文章

如何在不使用API 的情况下获得Google云端硬盘的可用空间?

在不使用 SharePoint API 的情况下列出 SharePoint 网站中的所有警报?

如何在不使用 GSON 或 android 中的任何其他库的情况下使用改造以字符串形式获得响应 [重复]

如何在不使用索引检查 mysql 表中的 100000 条记录等所有行的情况下获得一行? [关闭]

在不超过广播扩展的内存限制的情况下缩放 CMSampleBuffer 大小

如何在不使用databricks csv api的情况下直接将CSV文件读入spark DataFrame?