如何使用游标在Twitter API中使用c#迭代GET关注者/列表的结果集?

时间:2014-09-01 12:14:34

标签: c# api visual-studio-2012 twitter

我一直在尝试在GET关注者/列表API调用的结果集的下一页中获取数据。我可以使用前20个粉丝的数据获取默认数据集,而不是其他数据集。要获取其他关注者的数据,我必须使用next_cursor访问下一页但它不起作用。我尝试使用此链接中提到的伪代码。 https://dev.twitter.com/docs/misc/cursoring

是否必须使用它(这在开发站点中提到):

var api-path = "https://api.twitter.com/1.1/endpoint.json?screen_name=targetUser"

因为我一直在使用资源网址,

var resource_url = "https://api.twitter.com/1.1/followers/list.json";

我尝试将next_cursor附加到相同的资源URL。

var url_with_cursor = resource_url + "&cursor=" + 1463101490306580067;

然后创建了请求。

HttpWebRequest request = (HttpWebRequest)WebRequest.Create(url_with_cursor);

但我在获得回复时会在此行中收到异常。

WebResponse response = request.GetResponse();

我得到的错误是

The Remote Server returned an Error 401 Unauthorized

有人可以告诉游标的确切方法,或者将光标包含在请求中的确切方法。我正在使用asp.net C#Web应用程序。

这是我的代码,我的应用程序中定义了 oauth_token,oauth_token_secret,oauth_consumer_key,oauth_consumer_secret,oauth_version和oauth_signature_method

    var resource_url = "https://api.twitter.com/1.1/followers/list.json";
    var cursor = "-1";

    do
    {
        var url_with_cursor = resource_url + "&cursor=" + cursor;


        // unique request details
        var oauth_nonce = Convert.ToBase64String(
            new ASCIIEncoding().GetBytes(DateTime.Now.Ticks.ToString()));
        var timeSpan = DateTime.UtcNow
            - new DateTime(1970, 1, 1, 0, 0, 0, 0, DateTimeKind.Utc);
        var oauth_timestamp = Convert.ToInt64(timeSpan.TotalSeconds).ToString();

        // create oauth signature
        var baseFormat = "oauth_consumer_key={0}&oauth_nonce={1}&oauth_signature_method={2}" +
                        "&oauth_timestamp={3}&oauth_token={4}&oauth_version={5}";

        var baseString = string.Format(baseFormat,
                                    oauth_consumer_key,
                                    oauth_nonce,
                                    oauth_signature_method,
                                    oauth_timestamp,
                                    oauth_token,
                                    oauth_version
            //,Uri.EscapeDataString(status)
                                    );

        baseString = string.Concat("GET&", Uri.EscapeDataString(resource_url), "&", Uri.EscapeDataString(baseString));

        var compositeKey = string.Concat(Uri.EscapeDataString(oauth_consumer_secret),
                                "&", Uri.EscapeDataString(oauth_token_secret));

        string oauth_signature;
        using (HMACSHA1 hasher = new HMACSHA1(ASCIIEncoding.ASCII.GetBytes(compositeKey)))
        {
            oauth_signature = Convert.ToBase64String(
                hasher.ComputeHash(ASCIIEncoding.ASCII.GetBytes(baseString)));
        }

        // create the request header
        var headerFormat = "OAuth oauth_nonce=\"{0}\", oauth_signature_method=\"{1}\", " +
                           "oauth_timestamp=\"{2}\", oauth_consumer_key=\"{3}\", " +
                           "oauth_token=\"{4}\", oauth_signature=\"{5}\", " +
                           "oauth_version=\"{6}\"";

        var authHeader = string.Format(headerFormat,
                                Uri.EscapeDataString(oauth_nonce),
                                Uri.EscapeDataString(oauth_signature_method),
                                Uri.EscapeDataString(oauth_timestamp),
                                Uri.EscapeDataString(oauth_consumer_key),
                                Uri.EscapeDataString(oauth_token),
                                Uri.EscapeDataString(oauth_signature),
                                Uri.EscapeDataString(oauth_version)
                        );


        // make the request
        ServicePointManager.Expect100Continue = false;     

        HttpWebRequest request = (HttpWebRequest)WebRequest.Create(url_with_cursor);
        request.Headers.Add("Authorization", authHeader);
        request.Method = "GET";
        request.ContentType = "application/x-www-form-urlencoded";

        WebResponse response = request.GetResponse();



        string result = new StreamReader(response.GetResponseStream()).ReadToEnd();
        JObject j = JObject.Parse(result);
        JArray data = (JArray)j["users"];
        cursor = (String)j["next_cursor_str"];

} while (!cursor.Equals("0"));

感谢。

3 个答案:

答案 0 :(得分:1)

您应该通过授权请求进行不同的身份验证调用。一旦授予,您可以使用光标调用webresponse。请参阅下面的示例代码(特别注意完成身份验证的StartCreateCall方法。然后通过CallData方法检索Twitter中的数据):

public partial class twitter_followers : System.Web.UI.Page
{
    public string strTwiterFollowers { get; set; }
    private List<TwiterFollowers> listFollowers = new List<TwiterFollowers>();
    private string screen_name = string.Empty;

    // oauth application keys
    private string oauth_consumer_key = string.Empty;
    private string oauth_consumer_secret = string.Empty;

    // oauth implementation details
    private string resource_urlFormat = "https://api.twitter.com/1.1/followers/list.json?screen_name={0}&cursor={1}";

    // unique request details
    private string oauth_nonce = Convert.ToBase64String(new ASCIIEncoding().GetBytes(DateTime.Now.Ticks.ToString()));

    protected void Page_Load(object sender, EventArgs e)
    {
        //just get your request parameters from the config file.
        if (!string.IsNullOrEmpty(ConfigurationManager.AppSettings[GetVariableName(() => screen_name)])) {
            screen_name = ConfigurationManager.AppSettings[GetVariableName(() => screen_name)];
        }
        if (!string.IsNullOrEmpty(ConfigurationManager.AppSettings[GetVariableName(() => oauth_consumer_key)]))
        {
            oauth_consumer_key = ConfigurationManager.AppSettings[GetVariableName(() => oauth_consumer_key)];
        }
        if (!string.IsNullOrEmpty(ConfigurationManager.AppSettings[GetVariableName(() => oauth_consumer_secret)]))
        {
            oauth_consumer_secret = ConfigurationManager.AppSettings[GetVariableName(() => oauth_consumer_secret)];
        }
        StartCreateCall();
    }

    // Do the authenticate by an authorization request
    private void StartCreateCall() {
        // You need to set your own keys and screen name
        var oAuthUrl = "https://api.twitter.com/oauth2/token";

        // Do the Authenticate
        var authHeaderFormat = "Basic {0}";

        var authHeader = string.Format(authHeaderFormat,
            Convert.ToBase64String(Encoding.UTF8.GetBytes(Uri.EscapeDataString(oauth_consumer_key) + ":" +
            Uri.EscapeDataString((oauth_consumer_secret)))
        ));

        var postBody = "grant_type=client_credentials";

        HttpWebRequest authRequest = (HttpWebRequest)WebRequest.Create(oAuthUrl);
        authRequest.Headers.Add("Authorization", authHeader);
        authRequest.Method = "POST";
        authRequest.ContentType = "application/x-www-form-urlencoded;charset=UTF-8";
        authRequest.AutomaticDecompression = DecompressionMethods.GZip | DecompressionMethods.Deflate;

        using (Stream stream = authRequest.GetRequestStream())
        {
            byte[] content = ASCIIEncoding.ASCII.GetBytes(postBody);
            stream.Write(content, 0, content.Length);
        }

        authRequest.Headers.Add("Accept-Encoding", "gzip");

        WebResponse authResponse = authRequest.GetResponse();
        // deserialize into an object
        TwitAuthenticateResponse twitAuthResponse;
        using (authResponse)
        {
            using (var reader = new StreamReader(authResponse.GetResponseStream()))
            {
                JavaScriptSerializer js = new JavaScriptSerializer();
                var objectText = reader.ReadToEnd();
                twitAuthResponse = JsonConvert.DeserializeObject<TwitAuthenticateResponse>(objectText);
            }
        }
        //now we have been granted access and got a token type with authorization token from Twitter
        //in the form of a TwitAuthenticateResponse object, we can retrieve the data recursively with a cursor
        CallData(twitAuthResponse, authHeader, cursor);

        int totalFollowers = listFollowers.Count;
        lblTotalFollowers.Text = screen_name + " has " + listFollowers.Count + " Followers";

        Random objRnd = new Random();
        List<TwiterFollowers> randomFollowers = listFollowers.OrderBy(item => objRnd.Next()).ToList<TwiterFollowers>();
        foreach (TwiterFollowers tw in randomFollowers)
        {
            strTwiterFollowers = strTwiterFollowers + "<li><a target='_blank' title='" + tw.ScreenName + "' href=https://twitter.com/" + tw.ScreenName + "><img src='" + tw.ProfileImage + "'/><span>" + tw.ScreenName + "</span></a></li>";
        }
    }

    //Retrieve the data from Twitter recursively with a cursor
    private void CallData(TwitAuthenticateResponse twitAuthResponse, string authHeader, string cursor)
    {
        try {
            JObject j = GetJSonObject(twitAuthResponse, authHeader, cursor);
            JArray data = (JArray)j["users"];
            if (data != null)
            {
                foreach (var item in data)
                {
                    TwiterFollowers objTwiterFollowers = new TwiterFollowers();
                    objTwiterFollowers.ScreenName = item["screen_name"].ToString().Replace("\"", "");
                    objTwiterFollowers.ProfileImage = item["profile_image_url"].ToString().Replace("\"", "");
                    objTwiterFollowers.UserId = item["id"].ToString().Replace("\"", "");
                    listFollowers.Add(objTwiterFollowers);
                }

                JValue next_cursor = (JValue)j["next_cursor"];
                if (long.Parse(next_cursor.Value.ToString()) > 0)
                {
                    //Get the following data from Twitter with the next cursor
                    CallData(twitAuthResponse, authHeader, next_cursor.Value.ToString());
                }
            }
        } catch (Exception ex)
        {
            //do nothing
        }
    }

    private JObject GetJSonObject(TwitAuthenticateResponse twitAuthResponse, string authHeader, string cursor)
    {
        string resource_url = string.Format(resource_urlFormat, screen_name, cursor);
        if (string.IsNullOrEmpty(cursor))
        {
            resource_url = resource_url.Substring(0, resource_url.IndexOf("&cursor"));
        }

        HttpWebRequest fRequest = (HttpWebRequest)WebRequest.Create(resource_url);
        var timelineHeaderFormat = "{0} {1}";
        fRequest.Headers.Add("Authorization", string.Format(timelineHeaderFormat, twitAuthResponse.token_type, twitAuthResponse.access_token));
        fRequest.Method = "Get";
        WebResponse response = fRequest.GetResponse();
        string result = new StreamReader(response.GetResponseStream()).ReadToEnd();
        return JObject.Parse(result);
    }

    private string GetVariableName<T>(Expression<Func<T>> expr)
    {
        var body = (MemberExpression)expr.Body;
        return body.Member.Name;
    }

    private class TwitAuthenticateResponse
    {
        public string token_type { get; set; }
        public string access_token { get; set; }
    }

    private class TwiterFollowers
    {
        public string ScreenName { get; set; }
        public string ProfileImage { get; set; }
        public string UserId { get; set; }
    }
}

答案 1 :(得分:0)

你得到“401 Unauthorized” 你有没有检查你是否正确设置好一切? 证书?检查fiddler上的两个查询。

答案 2 :(得分:0)

Tweetinvi会让你更容易。

请访问https://github.com/linvi/tweetinvi/wiki/Get-All-Followers-Code,了解如何执行此操作,包括RateLimit处理。

不考虑RateLimits,您只需使用以下代码即可。

long nextCursor = -1;

do
{
    var query = string.Format("https://api.twitter.com/1.1/followers/ids.json?screen_name={0}", username);

    var results = TwitterAccessor.ExecuteCursorGETCursorQueryResult<IIdsCursorQueryResultDTO>(query, cursor: cursor).ToArray();

    if (results.Any())
    {
        nextCursor = results.Last().NextCursor;
    }
    else
    {
        nextCursor = -1;
    }
}
while (nextCursor != -1 && nextCursor != 0);