YQL×JSONPでクロスドメイン制約を超え、要素を取得するハナシ

んちゃ!

以前、
URLからタイトルを取得しHTMLのaタグを生成するサービスを公開しました | 戯言Vestige1.1
の中で、

URLに紐づくタイトルを取得させる際にクロスドメイン制約にひっかかってしまうため、
YQLを用いたAjaxでJSONP形式として要素を受け取らなければならず、
その実現方法を確認することに多くの時間を要してしまいました。

と言っていました。
今回はその詳細についてのエントリです。

想定読者
今回のエントリは、

  • javascriptのクロスドメイン制約に対する解決方法を模索している
  • (今回の解決方法である)YQLの用例を探している
  • YQL×JSONP(Ajax)で要素を受け取る方法を知りたい

という方向けです。
なので、
以下の基本的な知識・スキルを持っているあるいは学ぶことができる方であれば、
なおよいと思われます。

  • HTML(5)/CSS(3)/javascriptを用いたDOM操作
  • jQuery
  • Ajax
  • JSON(P)

実現したかった事
事の発端はこのサービスを、
HTML・CSS・javascriptだけでサクっと作成できるのではないかと考えたためです。
指定したURLのタイトルを取得するだけの小さなサービスだったので、
わざわざサーバを立てる必要はないと考えたわけですね。
言い換えると、
“javasciriptを用いて指定したURLのDOMを取得する”
というのが実現したいことでした。

クロスドメイン制約とは?
実現手段を調べていくうちに、一筋縄ではいかない事が判明します。
それが、javascriptのクロスドメイン制約です。
google先生からの助言や書店での立ち読みを進めていくと、
どうやらJSONPを用いればこれを解決できることがわかってきました
(それについてはこちらの記事が詳しいです)。
さらに、
タイトルなどの要素をJSONPで取得できれば、
後はそれを加工することでやりたい事が実現できそう、というのがわかります。
そこで、今回取り上げるYQLの存在を知ります。

YQLとは?その作り方・使い方とは?
こちらの記事を引用すると、

YQLとは米Yahoo! Developer Networkが提供している、ありとあらゆるWeb上のリソースにアクセスすることができる開発者向けのサービスです。
文法はSQLのようで独特ですが、要約すると
XML、HTML、RSS、CSVなどをJSONPに変換
WebAPIレスポンスの加工
キャッシュ機能つき
登録などをしなくても使える(利用制限等についてはYQL公式サイトをご参照ください)
こういった機能を持つ、汎用的なプロキシサービスです。

とあります。
なので今回は、

  • YQLを作成
  • 作成したYQLを呼び出すためのURLを生成
  • JSONPとしてAjaxで受け取る

ことが必要になります。これについては、以下の記事でも紹介されています。
YQLとgetJSON()の組みあわせが素敵すぎる件について – LabMemo
それYQLで出来るよ! – Weblog – hail2u.net

YQLの作成には、 YQL Console が欠かせません。
これは、YQLの結果をその場で確認することができる優れたWebサービスで、
今回もここで検証を行いました。
この度作成したサービスではDOMの最上位階層から辿ってタイトルを取得する必要があるので、以下の様なYQLを発行しています。
所謂条件文にはXpathを用いていることが分かるかと思います(Xpathについては、こちら)。

select head.title from html where url="blog.yo41sawada.jp/weblog/" and xpath="//*"

検証したYQLを呼び出すためのURLは、

  • YQLを呼び出すためのURL(不変)
  • YQLのクエリ部分
  • JSONとして受け取るよう指定する部分

から成り立たせることができます。
例えば、以下のようなURLです。

http://query.yahooapis.com/v1/public/yql?q=select%20head.title%20from%20html%20where%20url=%22http://www.yo41sawada.jp/a-tag_getter/a-tag_getter.html%22%20and%20xpath=%22*%22&format=json


その際、FirefoxプラグインのJSONViewなどを用いると、
上記URLを入力した結果をブラウザ上で確認することができるので非常に便利です。
なおcallback関数を指定する方法もありますが、今回そこまでの対応は必要ないと判断し、採用していません。

呼び出すべきURLを決めることができれば、
AjaxにてJSONPで取得できるようにすれば完成となります。
それは以下のように、jQueryを用いることで手軽に実現できます。

$.ajax({
url : yql_url, //呼び出したいURLを変数化していると仮定
dataType : "jsonp",
timeout : 7000,  //7秒でタイムアウト
success : function(json){
成功時の処理
},
error : function(XMLHttpRequest, textStatus, errorThrown){
エラー時の処理
},
complete : function(XMLHttpRequest, textStatus){
成功・エラーに関わらず、最後に実行される処理
}
});

受け取ったJSONPは成功時の引数に格納されるため、プロパティとして参照することが可能です。
例えば、以下のように変数に格納することもできます。

var results = json.query.results
var title = json.query.results.html.head.title;

後はDOMを操作するなど、煮るなり焼くなり後続の処理を記載すれば完成となります。

おわりに
javascriptのクロスドメイン制約に対して、
YQLを用い結果をAjaxにてJSONPで受け取る方法を紹介しました。
仮にYQLが使用できなくなってしまった場合は、
同一ドメイン内にサーバを用意してあげるのが賢明かもしれません。
もしかすると、
HTML5から対応したpostMessageで何とかなったりするのかもしれません。
それらについては、機会があれば検証、報告したいと思います。

この技術要素を用いて作成したサービスが、こちらです。
Let’s get ANCHOR from URL | powered by yo41sawada

参考リンク
URLからタイトルを取得しHTMLのaタグを生成するサービスを公開しました | 戯言Vestige1.1
YQL Console
[Web] JSONPを用いてクロスドメイン制約を超える – YoheiM .NET
YQLとgetJSON()の組みあわせが素敵すぎる件について – LabMemo
それYQLで出来るよ! – Weblog – hail2u.net
XPath による要素の指定 | すぐに忘れる脳みそのためのメモ
XMLのWebAPIを爆速で使いこなせるフレームワーク – Yahoo! JAPAN Tech Blog


コメントを残す

メールアドレスが公開されることはありません。 * が付いている欄は必須項目です

次のHTML タグと属性が使えます: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong> <img localsrc="" alt="">