Twitter4J:如何解决Twitter API的速率限制请求?

时间:2015-01-25 20:50:08

标签: java twitter twitter4j

我正在创建一个使用Twitter4J库与Twitter交互的java应用程序。 我想从twitter下载10 000个节点,然后对创建的图表进行统计。该图最初保存在数据集(.txt文件)中。 我还必须为每个节点保存足够的ReTweet(所以我必须检查他们的时间线)。

跳过twitter的实例化来执行查询,我有两个问题和疑问: 1)如何管理Twitter API在15分钟内插入插槽所需数量有限的问题?

我试过了:

public static RateLimitStatus getApplicationRateLimitStatus(Twitter twitter)
{
    try {
        Map<String ,RateLimitStatus> rateLimitStatus = twitter.getRateLimitStatus();
        for (String endpoint : rateLimitStatus.keySet()) 
        {
            if (endpoint.equals("/application/rate_limit_status"))
                return rateLimitStatus.get(endpoint);
        }
    } catch (TwitterException te) 
        {
            te.printStackTrace();
            System.out.println("Failed to get rate limit status: " + te.getMessage());
            System.exit(-1);
        }       
    return null; 
}

public static void control(Twitter twitter)
{
    RateLimitStatus app_rate_limit_st = null;
    RateLimitStatus user_timeline_limit_st = null;
    RateLimitStatus credentials_limit_st = null;
    RateLimitStatus friends_list_limit_st = null;
    RateLimitStatus followers_list_limit_st = null;
    int ctr_req = 7;

    try {
        if ((app_rate_limit_st = MyRateLimit.getApplicationRateLimitStatus(twitter)).getRemaining() < ctr_req)
        {
            System.out.println("I'm waiting "+app_rate_limit_st.getSecondsUntilReset()+" seconds for Application Rate Limit, app request remaining: "+app_rate_limit_st.getRemaining());
            Thread.sleep((long)app_rate_limit_st.getSecondsUntilReset()*1000);
            System.out.println("I woke up!!!");
        }
    }catch(InterruptedException e) {e.printStackTrace();}
}

在这段代码中,我只检查了请求ApplicationRequest类型,但在我的应用程序中,我还检查了所需类型的FriendList,FollowersList,UserTimeline和Credentials。

通过运行我的应用程序,提出了该通知 我已经超过了可用的应用程序数量,并且无法理解为什么。

2) 另一个问题是哪个算法应该继续下载节点。 我考虑过采用一个受欢迎的节点(有很多朋友和粉丝,并且互相交流很多)。 我试图接受节点,朋友,他的粉丝,以及朋友和朋友的追随者以及粉丝的追随者。 这是一个聪明的技巧?他们会更清楚吗?

感谢。

1 个答案:

答案 0 :(得分:1)

只考虑如何解决速率限制问题 - 创建多个twitter oauth凭证,您可以维护使用每个可用凭证配置的Twitter实例的列表/集合,当您达到说id1的速率限制时,您可以切换到使用id2来获取记录。

检查功能速率限制状态并进行切换,而不是使用getApplicationRateLimitStatus,这将帮助您根据该API的可用限制来规划交换机。

- 根据评论评论添加以下代码/评论,

您可以执行以下操作,对于您可以使用连接器的每个请求,在您的情况下,您可能需要缓存一些可用于进行下一次调用的信息,如sinceId和maxId。

您需要创建/注册多个Twitter帐户并为每个帐户生成凭据。我曾尝试过这种方法来为大约1M用户提取信息,这很有效。

您还可以缓存一些重复信息并保存少量点击到Twitter,例如在10人的网络中可能有一定比例的普通用户/关注者,因此查找用户信息可以在下一个请求中跳过以前获取的用户

getTweetConnector()方法将确保您获得一个已重置其ratelimit的连接器。

由于您是通过多个API获取信息,因此您可以批量处理特定请求的连接器,以便具有更高rateLimit的API可以拥有更多连接器。

public class TweetUserInfo {
private Set<Twitter> mTwitterConnectorsSet;
private BufferedReader mUserFileReader;

TweetUserInfo(){
    mTwitterConnectorsSet = new HashSet<Twitter>();
}

private void initTweetConnectors(String inFile) {
    BufferedReader br = null;
    try {
        String line = null;
        String[] lines = new String[4];
        int linesIndex = 0;
        br = new BufferedReader(new FileReader(inFile));

        while ((line = br.readLine()) != null) {
            if (linesIndex == 4) {
                createAndAddTwitterConnector(lines);
                linesIndex = 0;
            }
            lines[linesIndex] = line;
            ++linesIndex;
        }
        if (linesIndex == 4) {
            createAndAddTwitterConnector(lines);
        }

    } catch (IOException e) {
        e.printStackTrace();
    } finally {
        try {
            if (br != null)br.close();
        } catch (IOException ex) {
            ex.printStackTrace();
        }
    }
}

private void createAndAddTwitterConnector(String[] lines) {
    ConfigurationBuilder twitterConfigBuilder = new ConfigurationBuilder();
    twitterConfigBuilder.setDebugEnabled(true);

    for (int i = 0; i < lines.length; ++i) {
        String[] input = lines[i].split("=");

        if (input[0].equalsIgnoreCase("consumerkey")) {
            twitterConfigBuilder.setOAuthConsumerKey(input[1]);
        }
        if (input[0].equalsIgnoreCase("consumersecret")) {
            twitterConfigBuilder.setOAuthConsumerSecret(input[1]);
        }
        if (input[0].equalsIgnoreCase("accesstoken")) {
            twitterConfigBuilder.setOAuthAccessToken(input[1]);
        }
        if (input[0].equalsIgnoreCase("accesstokensecret")) {
            twitterConfigBuilder.setOAuthAccessTokenSecret(input[1]);
        }
    }
    Twitter twitter = new TwitterFactory(twitterConfigBuilder.build()).getInstance();
    mTwitterConnectorsSet.add(twitter);
}

private Twitter getTweetConnector() {
        for (Twitter tc : mTwitterConnectorsSet) {
            try {
                if (tc.getRateLimitStatus() != null) {
                    if (tc.getRateLimitStatus().containsKey("/users/lookup")) {
                        if (tc.getRateLimitStatus().get("/users/lookup") != null) {
                            System.out.println("tc - "+tc);
                            System.out.println("tc rate - "+tc.getRateLimitStatus().get("/users/lookup").getRemaining());
                            if (tc.getRateLimitStatus().get("/users/lookup").getRemaining() > 2) {
                                return tc;
                            }
                        }
                    }
                }
            } catch (TwitterException e) {
                e.printStackTrace();
            }
        }
    return null;
}

}

希望这有帮助。