因此,我正在尝试与某位追随者的朋友们交流。不是递归地挖掘,只是那个单一层次。

我能够将追随者拉得很好(看起来它可以处理超过75,000个追随者,所以我有90%的把握确定了那里的速率限制)。

但是我返回朋友的代码在返回15个关注者朋友之后抛出了身份验证错误。

换句话说,在这段代码中:

for (var i = 0; i < followerList.Count; i++)
{
  await followersFriends(followerList[i]);
}


i == 15时出现此错误:


  LinqToTwitter.TwitterQueryException
    HResult = 0x80131500
    Message = {“ request”:“ / 1.1 / friends / ids.json”,“ error”:“未授权。”}-请访问LINQ to Twitter FAQ(在HelpLink上)以获取有关解决此错误的帮助。


它似乎确实获得了15个列表,这是第16个抛出该列表的列表。我觉得这不是与速率限制相同的巧合,即使它是速率限制也很奇怪。

我将检查一下我们是否处于15的倍数上,并进行15分钟的暂停,但是,如果这种方法不起作用,那么有人是否有关于接下来可能发生的事情的理论? ?

ETA:我确实尝试通过followersFriends在每次运行时重做我的身份验证(基于应用程序)。没有帮助。

ETA2:

这是新的调用代码:

for (var i = 0; i < followerList.Count; i++)
{
  if (i % 15 == 0 && i != 0) {
    Console.WriteLine(DateTime.Now.ToString("h:mm:ss tt") + " - i = " + i + " and user = " + followerList[i]);
    PauseThatRefreshes("friends");
    RunMe();
  }

  await followersFriends(followerList[i]);
}


这是被调用的代码:

private async Task followersFriends(ulong uid)
{
  var twitterCtx2 = new TwitterContext(m_foo);

  Console.WriteLine(DateTime.Now.ToString("h:mm:ss tt") + " - *** Start Friend Get for " + uid.ToString() + " ***");

  long cursor = -1;

  do
  {
    var friendList = await (from friend in twitterCtx2.Friendship where friend.Type == FriendshipType.FriendIDs && friend.UserID == uid.ToString() && friend.Cursor == cursor select friend).SingleOrDefaultAsync();

    if (twitterCtx2.RateLimitRemaining <= 2)
    {
      Console.WriteLine(DateTime.Now.ToString("h:mm:ss tt") + " - *** Pausing A ***");
      Console.WriteLine(DateTime.Now.ToString("h:mm:ss tt") + " - Friends Rate Limit Remaining at Pause A: " +
        twitterCtx2.RateLimitRemaining.ToString());
      PauseThatRefreshes("friends");
    }

    if (friendList != null &&
      friendList.IDInfo != null &&
      friendList.IDInfo.IDs != null) {
      cursor = friendList.CursorMovement.Next;
      Console.WriteLine(DateTime.Now.ToString("h:mm:ss tt") + " - Friends Rate Limit Remaining: " + twitterCtx2.RateLimitRemaining.ToString());
      friendList.IDInfo.IDs.ForEach(id => Output(uid.ToString(), id.ToString()));
    }

    if (twitterCtx2.RateLimitRemaining <= 2)
    {
      Console.WriteLine(DateTime.Now.ToString("h:mm:ss tt") + " - *** Pause B ***");
      Console.WriteLine(DateTime.Now.ToString("h:mm:ss tt") + " - Friends Rate Limit Remaining at Pause B: " + twitterCtx2.RateLimitRemaining.ToString());
      PauseThatRefreshes("friends");
    }
  } while (cursor != 0);

  Console.WriteLine(DateTime.Now.ToString("h:mm:ss tt") + " - *** Stop Friend Get for " + uid.ToString() + " ***");
  Console.WriteLine(DateTime.Now.ToString("h:mm:ss tt") + " - Friends Rate Limit Remaining at stop: " + twitterCtx2.RateLimitRemaining.ToString());

  return;
}


ETA只是为了澄清,该代码被称为FollowersFriends。是的,我知道,我没有更改按钮名称= D这更多是关于收集数据,我更喜欢表单而不是命令行……我不知道为什么。无论如何,无论在这里还是那里:

        private async void button2_Click(object sender, EventArgs e)
    {

        var twitterCtx = new TwitterContext(m_foo);
        string[] header = { "Account,Follows" };
        File.WriteAllLines(@"C:\temp\followersFriends.txt", header);

        //List to store ids of followers of main account
        List<ulong> followerList = new List<ulong>();
        // get main accounts followers and put into an array
        long cursor = -1;
        Console.WriteLine(DateTime.Now.ToString("h:mm:ss tt") + " - *** Start Follower Get ***");
        do
        {

            var followers =
    await
    (from follower in twitterCtx.Friendship
     where follower.Type == FriendshipType.FollowerIDs &&
           follower.ScreenName == "[[redacted]]" &&
           follower.Cursor == cursor
     select follower)
    .SingleOrDefaultAsync();
            if (followers != null &&
                followers.IDInfo != null &&
                followers.IDInfo.IDs != null
                &&
                followers.CursorMovement != null)
            {
                cursor = followers.CursorMovement.Next;
                followers.IDInfo.IDs.ForEach(id =>
                  followerList.Add(id));
            }

            if (twitterCtx.RateLimitRemaining <= 2)
                PauseThatRefreshes("followers");
        } while (cursor != 0);
        Console.WriteLine(DateTime.Now.ToString("h:mm:ss tt") + " - *** Done Follower Get ***");

        for (var i = 0; i < followerList.Count; i++)
        {
            if (i % 15 == 0 && i != 0)
            {
                Console.WriteLine(DateTime.Now.ToString("h:mm:ss tt") + " - i = " + i
                    + " and user = " + followerList[i]);
                PauseThatRefreshes("friends");
                RunMe();
            }
            await followersFriends(followerList[i]);
        }
    }

最佳答案

如您的注释中所述,遇到TwitterQueryException帐户时,将引发带有“未授权”消息的1963joeym。检查此帐户,我可以看到他们已经保护了它。 “受保护”的概念意味着除非该人“授权”您的帐户,否则任何人都无法看到该人的帐户或相关活动。由于他们尚未授权尝试查询其朋友列表的帐户,因此您将从Twitter收到HTTP 401未经授权。因此,出现“未授权”消息的原因。

尽管用户实体具有bool Protected属性,但根据您的情况进行检查并不现实,因为您仅使用ID列表,而没有完整的User实例可用。在这种情况下,您唯一可以做的就是处理异常并从那里恢复。有两个地方可以处理此异常:(1)查询原始好友列表时,和(2)查询好友的好友列表时,如下所示:

        var allFollowerIds = new List<ulong>();
        Friendship followers = null;
        long cursor = -1;
        do
        {
            try
            {
                followers =
                    await
                    (from follower in twitterCtx.Friendship
                     where follower.Type == FriendshipType.FollowerIDs &&
                           follower.UserID == "1039951639" &&// "15411837" &&
                           follower.Cursor == cursor &&
                           follower.Count == 500
                     select follower)
                    .SingleOrDefaultAsync();
            }
            catch (TwitterQueryException tqExUnauthorized) when (tqExUnauthorized.StatusCode == HttpStatusCode.Unauthorized)
            {
                Console.WriteLine("This user hasn't given your account permission to view their account.");
            }
            catch (TwitterQueryException tqe)
            {
                Console.WriteLine(tqe.ToString());
                break;
            }

            if (followers != null &&
                followers.IDInfo != null &&
                followers.IDInfo.IDs != null)
            {
                cursor = followers.CursorMovement.Next;

                allFollowerIds.AddRange(followers.IDInfo.IDs);
            }

        } while (cursor != 0);

        cursor = -1;
        foreach (var uid in allFollowerIds)
        {
            Console.WriteLine(DateTime.Now.ToString("h:mm:ss tt") + " - *** Start Friend Get for " + uid.ToString() + " ***");

            do
            {
                Friendship friendList = null;
                try
                {
                    friendList = await (from friend in twitterCtx.Friendship where friend.Type == FriendshipType.FriendIDs && friend.UserID == uid.ToString() && friend.Cursor == cursor select friend).SingleOrDefaultAsync();
                }
                catch (TwitterQueryException tqExUnauthorized) when (tqExUnauthorized.StatusCode == HttpStatusCode.Unauthorized)
                {
                    Console.WriteLine("This user hasn't given your account permission to view their account.");
                }

                if (twitterCtx.RateLimitRemaining <= 2)
                {
                    Console.WriteLine(DateTime.Now.ToString("h:mm:ss tt") + " - *** Pausing A ***");
                    Console.WriteLine(DateTime.Now.ToString("h:mm:ss tt") + " - Friends Rate Limit Remaining at Pause A: " +
                      twitterCtx.RateLimitRemaining.ToString());
                    //PauseThatRefreshes("friends");
                }

                if (friendList != null &&
                  friendList.IDInfo != null &&
                  friendList.IDInfo.IDs != null)
                {
                    cursor = friendList.CursorMovement.Next;
                    Console.WriteLine(DateTime.Now.ToString("h:mm:ss tt") + " - Friends Rate Limit Remaining: " + twitterCtx.RateLimitRemaining.ToString());
                    //friendList.IDInfo.IDs.ForEach(id => Output(uid.ToString(), id.ToString()));
                }

                if (twitterCtx.RateLimitRemaining <= 2)
                {
                    Console.WriteLine(DateTime.Now.ToString("h:mm:ss tt") + " - *** Pause B ***");
                    Console.WriteLine(DateTime.Now.ToString("h:mm:ss tt") + " - Friends Rate Limit Remaining at Pause B: " + twitterCtx.RateLimitRemaining.ToString());
                    //PauseThatRefreshes("friends");
                }
            } while (cursor != 0);

            Console.WriteLine(DateTime.Now.ToString("h:mm:ss tt") + " - *** Stop Friend Get for " + uid.ToString() + " ***");
            Console.WriteLine(DateTime.Now.ToString("h:mm:ss tt") + " - Friends Rate Limit Remaining at stop: " + twitterCtx.RateLimitRemaining.ToString());
        }


请注意,我在try子句中使用了when子句,专门针对401未经授权的情况,下面重复:

        catch (TwitterQueryException tqExUnauthorized) when (tqExUnauthorized.StatusCode == HttpStatusCode.Unauthorized)
        {
            Console.WriteLine("This user hasn't given your account permission to view their account.");
        }


对于好友列表,这使您可以仅处理Unauthorized部分,并仍然保护不符合该条件的任何其他TwitterQueryException。对于朋友的朋友列表,您只需要处理Unauthorized异常,并让查询继续对剩余的朋友进行迭代。

关于c# - C#-列出好友-击中身份验证失败过程,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/51119551/

10-13 00:05