お久しぶりです.N.Mです.最近は趣味でTwitter APIを使ったGUIアプリケーションをC#で作ってます(C#だとGUIアプリケーションが作りやすいと思ったので).今後不定期で,その制作過程で大変だったことを発信していければと思います.今回はその第1弾.
(次回はウィンドウサイズの調整について)
今はこんな感じの,直近のツイートから誰がTL上にいるのかをリストアップするアプリを作っています.
(アプリケーション自体は,ここで配布しております.今後も更新予定です!)
↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓
CoreTweetの認証
Twitter APIについてはC#のライブラリ"CoreTweet"を利用していまして,ここにも認証の仕方が書いてあるのですが,そのアカウントでアプリを使うことを認証した後に,7桁のPINコードが表示されます.APIをつかうために,そのPINコードを手動で入力するか,HTML解析するかしてOAuth.GetTokens
に渡す必要があります.手動で入力する方法はたくさん情報が出てきたので,最初はそれを採用してましたが,使ってるうちに手入力が面倒になったので,今回 HTML解析による取得 に挑戦しました.
環境・前提
- Visual Studio 2017で開発
- Twitter APIの利用のためにCoreTweetを使用
- WPFアプリケーションを制作(Formsではない)
仕組み
認証ページは最初のURLはhttps://api.twitter.com/oauth/authorize
の後にいろいろ文字列がついた状態になっています.そして,認証してもしなくても,最終的にURLがhttps://api.twitter.com/oauth/authorize
になります.認証した場合はHTML内に
<code>7桁のPINコード</code>
が埋め込まれています(そして<code>
タグはページのこの部分にしか出てきません).なので,やるべきこととしては
- 認証ページを表示して,ユーザに認証させる
- ページのリンクが
https://api.twitter.com/oauth/authorize
になったら,ページのHTMLコードを取得する. - HTMLソースから
<code>
の文字列を検索し,あれば後ろの7桁のPINコードを取り出し,認証する(なければ認証失敗のエラーを出す).
となります.
1. 認証ページを表示させる
CoreTweetの日本語WikiだとSystem.Diagnostics.Process.Start
で認証ページを表示していますが,HTMLソースを抜き取るのが難しそうだったので,認証ページの表示はWPFアプリケーションにWebBrowser
のコンポーネントを埋め込むことにしました('twitterWeb'と命名しました).で,WebBrowser
のNavigate
メソッドで認証ページのURLに飛べば表示できます.
2. ページのURIの取得,HTMLコードの取得
ここでいろいろつまづきました.つまづいたポイントとしては
- WebBrowserがnullで参照できなかった.
- WPF(
System.Windows.Controls
)ではなく,Formsのほう(System.Windows.Forms
)の情報ばかり出て混乱した. - WPFのWebBrowserからHTMLを抜き取る方法が分からなかった.
の3点ですね.
まず,1点目の参照の問題は,Navigate
メソッドを呼び出したあとに,WebBrowser
のURLを確認しようとしたんですけど,そのタイミングだと,まだ処理が完了してないのでnullが返ってきてしまうそうです.なので,WebBrowser
の処理が完了した際に呼ばれるイベントハンドラLoadCompleted
で,もろもろの処理を行います.
twitterWeb.Navigate(session.AuthorizeUri);
LoadCompletedEventHandler twitterWebUpdate = null;
twitterWebUpdate = (tSender, e) =>
{
string pin = "";
string finishedUrl = @"https://api.twitter.com/oauth/authorize";
string url = twitterWeb.Source.AbsoluteUri;
if (url == finishedUrl)
{
//ここにHTMLソースの取得とPINコードの抽出処理を実装
}
};
twitterWeb.LoadCompleted += twitterWebUpdate;
finishedURL
に認証後に行くはずのページのURLを,URL
にtwitterWeb
の現在のページのURLを格納しておき,この2つが一致したら認証後のページに行ったと判断します.
WebBrowser
からのHTMLの取得ですが,Visual StudioのプロジェクトでCOMのmshtmlを参照するようにして,mshtml.IHTMLDocument2
を介して,取得するようです(参考).
HTML抽出部分を加えるとこんな感じ
twitterWeb.Navigate(session.AuthorizeUri);
LoadCompletedEventHandler twitterWebUpdate = null;
twitterWebUpdate = (tSender, e) =>
{
string pin = "";
string finishedUrl = @"https://api.twitter.com/oauth/authorize";
string url = twitterWeb.Source.AbsoluteUri;
if (url == finishedUrl)
{
mshtml.IHTMLDocument2 doc = (mshtml.IHTMLDocument2)twitterWeb.Document;
string html = doc.body.innerHTML;
//ここにPINコードの抽出処理を実装
}
};
twitterWeb.LoadCompleted += twitterWebUpdate;
3. PINコードの抽出
ここまでできれば,あとはhtml
から<code>
の文字列をIndexOf
メソッドで検索して,
パパパっとSubstring
メソッドでPINコードの7桁の数字を抽出して終わり!
twitterWeb.Navigate(session.AuthorizeUri);
LoadCompletedEventHandler twitterWebUpdate = null;
twitterWebUpdate = (tSender, e) =>
{
string pin = "";
string finishedUrl = @"https://api.twitter.com/oauth/authorize";
string url = twitterWeb.Source.AbsoluteUri;
if (url == finishedUrl)
{
mshtml.IHTMLDocument2 doc = (mshtml.IHTMLDocument2)twitterWeb.Document;
string html = doc.body.innerHTML;
int codeIndex = html.IndexOf("<code>");
if (codeIndex >= 0)
{
//<code>があった=認証に成功した場合
pin = html.Substring(codeIndex + 6, 7);
t = OAuth.GetTokens(session, pin);
}
else
{
//<code>がなかった=認証に失敗した場合
MessageBox.Show("認証に失敗しました.");
}
}
};
twitterWeb.LoadCompleted += twitterWebUpdate;
これでTokens
変数 t
を介して,Twitter APIをいじることができます.
補足
- 認証ページにはほかにもリンクがありましたが,そこに飛ぼうとすると新しいタブで開かれるためか,Internet Explorerが新規で実行されます.
WebBrower
側のページは認証のリンク以外では飛ばなかったので,この仕組みでもうまくいっているようです.