【问题标题】:How to avoid to fetch a list of followers of the same Twitter user that was displayed before如何避免获取之前显示的同一 Twitter 用户的关注者列表
【发布时间】:2017-12-14 14:55:17
【问题描述】:

我对编码很陌生,但遇到了一些问题。我想在 Twitter 中显示某些特定用户的追随者......的追随者。我已经对此进行了编码,并且可以设置深度限制。但是,在使用小样本运行代码时,我发现我再次遇到了相同的用户,并且我的代码重新显示了这些用户的关注者。我怎样才能避免这种情况并跳到下一个用户?您可以在下面找到我的代码:

顺便说一句,在运行我的代码时,我遇到了 401 错误。在我正在处理的列表中,有一个私人用户,当我的代码捕获该用户时,它就会停止。另外,我该如何处理这个问题?我想跳过这些用户并阻止我的代码停止。

提前感谢您的帮助!

PS:我知道在处理大样本时会遇到 429 错误。解决这些问题后,我计划回顾相关讨论以处理。

public class mainJava {
    public static Twitter twitter = buildConfiguration.getTwitter();

    public static void main(String[] args) throws Exception {
        ArrayList<String> rootUserIDs = new ArrayList<String>();
        Scanner s = new Scanner(new File("C:\\Users\\ecemb\\Desktop\\rootusers1.txt"));
        while (s.hasNextLine()) {
            rootUserIDs.add(s.nextLine());
        }
        s.close();

        for (String rootUserID : rootUserIDs) {
            User rootUser = twitter.showUser(rootUserID);
            List<User> userList = getFollowers(rootUser, 0);
        }
    }

    public static List<User> getFollowers(User parent, int depth) throws Exception {
        List<User> userList = new ArrayList<User>();
        if (depth == 2) {
            return userList;
        }
        IDs followerIDs = twitter.getFollowersIDs(parent.getScreenName(), -1);
        long[] ids = followerIDs.getIDs();
        for (long id : ids) {
            twitter4j.User child = twitter.showUser(id);
            userList.add(child);
            getFollowers(child, depth + 1);
            System.out.println(depth + "th user: " + parent.getScreenName() + " Follower: " + child.getScreenName());
        }
        return userList;
    }
}

【问题讨论】:

    标签: api twitter duplicates twitter4j


    【解决方案1】:

    我想可以针对这个特定问题实施图形搜索算法。我选择了广度优先搜索算法,因为首先访问根用户的关注者会更好。您可以查看此link 以了解有关算法的更多信息。

    这是我针对您的问题的实现:

    public List<User> getFollowers(User parent, int startDepth, int finalDepth) {
        List<User> userList = new ArrayList<User>();
        Queue<Long> queue = new LinkedList<Long>();
        HashMap<Long, Integer> discoveredUserId = new HashMap<Long, Integer>();
    
        try {
            queue.add(parent.getId());
            discoveredUserId.put(parent.getId(), 0);
    
            while (!queue.isEmpty()) {
                long userId = queue.remove();
                int discoveredDepth = discoveredUserId.get(userId);
                if (discoveredDepth == finalDepth) {
                    continue;
                }
                User user = twitter.showUser(userId);
                handleRateLimit(user.getRateLimitStatus());
                if (user.isProtected()) {
                    System.out.println(user.getScreenName() + "'s account is protected. Can't access followers.");
                    continue;
                }
                IDs followerIDs = null;
                followerIDs = twitter.getFollowersIDs(user.getScreenName(), -1);
    
                handleRateLimit(followerIDs.getRateLimitStatus());
                long[] ids = followerIDs.getIDs();
                for (int i = 0; i < ids.length; i++) {
                    if (!discoveredUserId.containsKey(ids[i])) {
                        discoveredUserId.put(ids[i], discoveredDepth + 1);
                        User child = twitter.showUser(ids[i]);
                        handleRateLimit(child.getRateLimitStatus());
                        userList.add(child);
                        if (discoveredDepth >= startDepth && discoveredDepth < finalDepth) {
                            System.out.println(discoveredDepth + ". user: " + user.getScreenName() + " has " + user.getFollowersCount() + " follower(s) " + (i + 1) + ". Follower: " + child.getScreenName());
                        }
                        queue.add(ids[i]);
                    } else {//prints to console but does not check followers. Just for data consistency
                        User child = twitter.showUser(ids[i]);
                        handleRateLimit(child.getRateLimitStatus());
                        if (discoveredDepth >= startDepth && discoveredDepth < finalDepth) {
                            System.out.println(discoveredDepth + ". user: " + user.getScreenName() + " has " + user.getFollowersCount() + " follower(s) " + (i + 1) + ". Follower: " + child.getScreenName());
                        }
                    }
                }
            }
        } catch (TwitterException e) {
            e.printStackTrace();
        }
        return userList;
    }
    
    //There definitely are more methods for handling rate limits but this worked for me well
    private void handleRateLimit(RateLimitStatus rateLimitStatus) {
        //throws NPE here sometimes so I guess it is because rateLimitStatus can be null and add this conditional expression
        if (rateLimitStatus != null) {
            int remaining = rateLimitStatus.getRemaining();
            int resetTime = rateLimitStatus.getSecondsUntilReset();
            int sleep = 0;
            if (remaining == 0) {
                sleep = resetTime + 1; //adding 1 more second
            } else {
                sleep = (resetTime / remaining) + 1; //adding 1 more second
            }
    
            try {
                Thread.sleep(sleep * 1000 > 0 ? sleep * 1000 : 0);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }
    

    在此代码中,HashMap&lt;Long, Integer&gt; discoveredUserId 用于防止程序重复检查相同的用户并存储我们与该用户接触的深度。

    对于私人用户,twitter4j 库中有 isProtected() 方法。

    希望这个实现有所帮助。

    【讨论】:

    • 我突然想起要添加的另一件事,如果用户的帐户受到保护,但我们授予应用程序权限的用户正在关注该受保护用户,我们也可以访问该帐户的关注者。我不知道我表达清楚了没有,但是可以添加这样的东西......
    猜你喜欢
    • 1970-01-01
    • 2015-06-20
    • 2017-09-08
    • 1970-01-01
    • 2013-02-02
    • 2017-10-20
    • 2014-08-08
    • 2012-07-20
    • 1970-01-01
    相关资源
    最近更新 更多