Kindle Launcher ネタの続きです。
どうせならば、購入済みの一覧を拾ってきて、それに対してセカンダリタイルを付けれたほうが便利ですよね。ということで、購入リストを Kindle Cloud Reader から取得します。
Kindle Cloud Reader 自体がブラウザなので、なんとかなるだろう、という予想のもとに進めて方針を立てます。
- WebBrowser を使って Kindle Cloud Reader を表示する。
- 中身の DOM を拾って ASIN のリストを取得する。
な感じで ok でしょうってことで。
実際やってみると、いくつか難関があって、
- WebBrowser で接続するときに User-Agent を偽装しないといけない。
- WebBrowser 出 iframe 内ので HTML をどうやって取るのか?
というところです。本来はWindows ストアアプリとして作りたいところですが、WinRT の WebView と使うとまともに動かないので、WPF の WebBrowser を使います。HttpClient で直接データを持ってきてもよいのですが、購入リスト自体が iframe になっているのと、HTML のパースが面倒なのでパスします。そのうち、HTML のパーサーを作って試してみましょう。
■WebBrowser で User-Agent を偽装する
何故、偽装が必要かというと、そのまま WebBrowser で呼び出したときには、
こんな画面が出て接続ができません。そんな訳で、User-Agent を偽装しています。
private void OnClickCheck(object sender, RoutedEventArgs e)
{
// url を取得
string url = "http://read.amazon.co.jp" + "?dummy=" + DateTime.Now.Ticks.ToString();
string ua = "User-Agent: Mozilla/5.0 (Windows NT 6.3; WOW64; Trident/7.0; rv:11.0) like Gecko"; // IE
wb.Navigate(new Uri(url), null, null, ua);
}
偽装自体は簡単で、Navigate メソッドの第4引数に設定します。ここにヘッダを追加できるので、複数追加したいときは “rn” で追加すればよいそうです。すると、初回だけ Kindle のログイン画面が出て、その後はブラウザの cookie(かな?)が使われます。
URL に dummy を渡しているのはキャッシュが使われないようにするためです。
■購入リストを取得する
購入リストは iframe の中にあります。WebBrowser.Document が mshtml.HTMLDocument にあたるので、これを使って DOM で解析していきます。mshtml 自体は、参照設定で「アセンブリ」→「拡張」にある「Microsoft.mshtml」をチェックします。
結構、手間取ったのですが、iframe の中身を取るためには、doc.frames.item(0) な感じで iframe を取ってきて、mshtml.HTMLWindow2 で iframe のウィンドウを取得します。その後は、再び document プロパティで解析するというパターンですね。
private void OnClickGetList(object sender, RoutedEventArgs e)
{
var doc = wb.Document as mshtml.HTMLDocument;
var iwin = doc.frames.item(0) as mshtml.HTMLWindow2;
var idoc = iwin.document as mshtml.HTMLDocument;
var titles = idoc.getElementById("titles_inner_wrapper");
vm.Books.Clear();
var books = vm.Books;
foreach (mshtml.IHTMLElement it in titles.children)
{
var id = it.getAttribute("id") as string;
books.Add(GetBook(it));
Debug.WriteLine(id);
}
}
上記の方法は、WPF の WebBrowser でやった方法ですが、Windows デスクトップアプリの WebBrowser では次のようになります。既に、HtmlDocument が定義されているのでそのまま使います。iframe に対しては、GetElementById を使っては取れないので、Frames コレクションから直接取ってきます。
private void button2_Click(object sender, EventArgs e)
{
var doc = webBrowser1.Document;
// var iframe = doc.GetElementById("KindleLibraryIFrame");
var iwin = doc.Window.Frames[0];
var idoc = iwin.Document;
var titles = idoc.GetElementById("titles_inner_wrapper");
var ids = new List<string>();
foreach ( HtmlElement it in titles.Children ) {
ids.Add(it.Id);
Debug.WriteLine(it.Id);
}
}
購入一覧の場合は、最初の frame にあるので無条件に 0 を指定していますが、複数の iframe がある場合はチェックが必要でしょう。
こうすることで、WebBrowser を使って Kindle の購入一覧を取得できます。
お次は、取得した履歴をどうやってストアアプリと連携させるか、のトリックを紹介しましょう。


