2013/06/15

【C#でTwitter】ユーザタイムラインを取得する(API v1.1)

エラーにくじけたりもしたけれど、私はげんきです。

このエントリを投稿する頃にはAPI1.0はすでに廃止されると思います。
そんな中、なんとかAPI1.1でユーザタイムラインを取得することができました。

その方法をまとめます。


以下も合わせてどうぞ。


http://kuroeveryday.blogspot.jp/2013/05/ctwitterapi-v10.html
【C#でTwitter】ユーザタイムラインを取得する(API v1.0)








http://kuroeveryday.blogspot.jp/2013/06/ctwitterapi11.html
【C#でTwitter】タイムライン取得で多発するエラーに挫折しそう(API1.1)










0.Timeline取得前処理



AccessTokenとAccessSecretTokenを取得します。
取得方法は、以下のエントリをご参照ください。

http://kuroeveryday.blogspot.jp/2013/04/ctwitteroauth.html
【C#でTwitter】OAuth認証を行う[デスクトップクライアント版]









私の場合、取得したAccessTokenとAccessSecretTokenをXMLファイルに保存しており、最初にXMLファイルから設定情報を読み込んでいます。

ですので、
  settings.accessToken → AccessToken
  settings.accessSecretToken → AccessSecretToken
のように読み替えてください。

XMLファイルから読み書きする方法はこちら → C#で設定をXMLファイルに保存・読み込みする
 

//----------------------------------------
// とりあえず定数
//----------------------------------------

const string USER_TIMELINE = "https://api.twitter.com/1.1/statuses/user_timeline.json";
const string AUTHHEADER_BASE = "OAuth oauth_consumer_key=\"{0}\", oauth_nonce=\"{1}\", oauth_signature=\"{2}\",oauth_signature_method=\"{3}\", oauth_timestamp=\"{4}\", oauth_token=\"{5}\", oauth_version=\"{6}\"";


//----------------------------------------
// 0.Timeline取得前処理
//----------------------------------------

// セッティングファイル読み込み
XmlSerializer serializer = new XmlSerializer(typeof(TwitSettings));
FileStream fs = new FileStream(Directory.GetCurrentDirectory() + "\\" + SETTING_FILENAME, FileMode.Open);
TwitSettings settings = (TwitSettings)serializer.Deserialize(fs);


AccessTokenやAccessSecretTokenが取得できない場合は、
Twitter Developersから「My applications」を選択し、「Details」タブを見てください。

もし、AccessTokenが表示されていない場合は、「Create my access token」ボタンをクリックしてください。



1.パラメータ作成



次にTwitter APIを叩くためのパラメータを作成します。
サードパーティ製を使わないと言いながらここでは「OAuthBase.cs」を使用しています。


使い方は、「【C#でTwitter】OAuth認証を行う[デスクトップクライアント版]」を参照してください。


//----------------------------------------
// 1.パラメータ作成
//----------------------------------------

OAuthBase oauth = new OAuthBase();
string timestamp = oauth.GenerateTimeStamp();
string nonce = oauth.GenerateNonce();

string normalizedUrl, normalizedReqParams;
normalizedUrl = normalizedReqParams = string.Empty;

string reqUrl = USER_TIMELINE;
Uri uri = new Uri(reqUrl);   

string signature = oauth.GenerateSignature(
    uri
    , CONSUMER_KEY
    , CONSUMER_SECRET
    , settings.AccessToken
    , settings.AccessSecretToken
    , "GET"
    , timestamp
    , nonce
    , OAuthBase.SignatureTypes.HMACSHA1
    , out normalizedUrl
    , out normalizedReqParams);

signature = HttpUtility.UrlEncode(signature);


TimeStamp


timestampは素直にOAuthBaseのGenerateTimeStampメソッドの戻り値を使います。


Nonce


nonceは「【C#でTwitter】タイムライン取得で多発するエラーに挫折しそう(API1.1) 」で書きましたが、
OAuthBaseのGenerateNonceをそのまま使ってもエラーになってしまいました。

※訂正します。OAuthBaseのGenerateNonceメソッドの戻り値をそのまま使ってもタイムラインを取得することができました。どうやら原因は他にあったようです。


Signature



httpMethodは”GET”、SignatureTypeは”HMAC-SHA1”を設定し、それ以外は指定された通りそのまま渡します。

Signatureは”BOhSpoUQIcXIjIoiuJ7Mle3o76I=”のように返ってきます。
末尾の”=”をエスケープシーケンスに変換する必要があります。

そのため、HttpUtility.UrlEnodeメソッドを使用して”%3d”に変換しています。
HttpUtilityを使用するには参照設定に「System.Web」を追加し、ついでに名前空間「System.Web」を追加します。



2.HTTPリクエスト作成



次に1.で作成したパラメータを使ってHTTPリクエストを作成します。
HTTPリクエストをTwitterのサーバに投げることで、サーバ側から何らかの情報が返ってきます。
※「HTTPの基礎」 については後日まとめます。

//----------------------------------------
// 2.HTTPリクエスト作成
//----------------------------------------

HttpWebRequest req = (HttpWebRequest)WebRequest.Create(reqUrl);

string authHeader = string.Format(AUTHHEADER_BASE
                 , CONSUMER_KEY
                 , nonce
                 , signature
                 , "HMAC-SHA1"
                 , timestamp
                 , settings.AccessToken
                 , "1.0"
                 );

req.Method = "GET";
req.ContentType = "application/x-www-form-urlencoded";
req.Headers.Add("Authorization", authHeader);


authHeaderを以下の形式で生成します。
※”Authorization:”の部分は後で追加するので、authHeader作成時は不要です。

Authorization: OAuth oauth_consumer_key="CONSUMER_KEY", oauth_nonce="NONCE", oauth_signature="SIGNATURE", oauth_signature_method="HMAC-SHA1", oauth_timestamp="TIMESTAMP", oauth_token="ACCESS_TOKEN", oauth_version="1.0"

HttpMethodはSignature作成時と同じ”GET”
ContentTypeはおまじない…かな?




3.Timeline取得



私の場合、ここが「401:Unauthorized」エラーを発生させた原因でした。
HTTPリクエストのレスポンスをGetResponseで取得する前に、GetResponseStreamをしていたのがエラーの原因でした。


//----------------------------------------
// 3.Timeline取得
//----------------------------------------

Encoding enc = Encoding.UTF8;

WebResponse res = req.GetResponse();
Stream resStream = res.GetResponseStream();

StreamReader sr = new StreamReader(resStream, enc);
Console.WriteLine(sr.ReadToEnd());

resStream.Close();
sr.Close();


ここでは、取得したJSON形式のデータをそのままコンソールに書き出しています。
取得した内容はこの通りです。

まだ整形される前なのと、日本語対応がされていないので内容はさっぱりですが、
一応ユーザタイムラインを取得することができました。

user_idやcount、since_idなどのパラメータの渡し方は後日まとめます。




以上

2 件のコメント :

  1. 誤り
    const string AUTHHEADER_BASE = "OAuth
    ....,auth_signature_method=\"{3}\",...

    正解
    const string AUTHHEADER_BASE = "OAuth
    ...., oauth_signature_method=\"{3}\",...

    返信削除
    返信
    1. ご指摘いただけなかったらずっと気付かないままでした。
      ありがとうございました。

      Authorizationヘッダの定数を修正しました。

      削除