スポンサーサイト

上記の広告は1ヶ月以上更新のないブログに表示されています。
新しい記事を書く事で広告が消せます。

ブログランキング・にほんブログ村へ

--.--.-- | スポンサー広告

Android開発 #14 HTMLのパース

 NextTrain互換アプリであるjNTrainにWebからの時刻表取り込み機能を組み込めないかと研究中。

 というわけで、先日JavaでのHTTP通信を試し、こちらは問題なさそう。
 時刻表のURLまでたどり着ければ、時刻表データの含まれているHTMLファイルが取得できるわけですが、このままではデータとして扱いにくい。 HTMLは結局のところテキストファイルですので、一定の法則性を見つけ出して抜き出す文字列操作だけでも何とかなるのですが、ちゃんとHTML構文とかをたどっていったほうが後々仕様変更にも対応しやすいのではと、HTMLパースの方法を調べてみました。


 JavaのHTMLパーサにはいろんなものがあるようなのですが、AndroidのSDKでも使用されているというTagSoupというものを使ってみようかと前回の記事でも触れていました。
 今回は、実際にTagSoupを使ってHTMLの読み込みを試してみました。 いろいろ試すのもめんどくさいので、使いやすそうであればそのまま使っちゃおうと。 そんな目論見。

 ソースはこんな感じ。

    try
    {
        Parser parser = new Parser();
        httpHandler handler = new httpHandler();
        parser.setContentHandler(handler);
        parser.parse(new InputSource(http.getInputStream()));
    }
    catch (SAXException e)
    {
        System.out.print(e.getMessage());
    }
    http.disconnect();

 むちゃくちゃ短いですが、パーサを作成して読み込みさせる部分は正味これだけ。
 TagSoupのHTMLパースに関してググって見ると、たいてい「パーサにSAXのContentHandlerをセットするだけ」という解説に行きつく。

 「ちょっとなにいってるかわかんない」orz

 ここで拒否反応を起こしては駄目だ。 某兵器に搭乗することを強要されたシンジくんの心境になりつつも、サンプルのコードを探し出して読み解いてみると確かに、パーサをnew、setContentHandler()でハンドラをセット、parse()で入力するHTMLソースをセットと、これだけしかしてない。
 で、HTML解析にてタグ等の各要素はハンドラであるContentHandler(ここではhttpHandlerクラス)内のメソッドが呼ばれて引き渡されるわけですね。

 とりあえずContentHandlerをインプリメントしたクラスをセットして実行してみると、startElement()、endElement()などの関数が呼び出されて、引き数にタグ情報などがセットされている模様。
public class httpHandler implements ContentHandler {

    int mLevel = 0;
   
    @Override
    public void startDocument() throws SAXException {
        System.out.println("startDocument");
    }
   
    @Override
    public void endDocument() throws SAXException {
        System.out.println("endDocument");
    }
   
    @Override
    public void startElement(String uri, String localName, String qName,
            Attributes atts) throws SAXException {
        System.out.print("startElement:");
        for(int i = 0; i < mLevel; i++) System.out.print(" ");
        System.out.print("<" + localName + "> ");
        for( int ii = 0; ii < atts.getLength(); ii++)
        {
            System.out.print(" ["+atts.getQName(ii)+"="+atts.getValue(ii)+"]");
        }
        System.out.println();
        mLevel ++;
    }

    @Override
    public void endElement(String uri, String localName, String qName)
            throws SAXException {
        mLevel --;

        System.out.print("endElement  :");
        for(int i = 0; i < mLevel; i++) System.out.print(" ");
        System.out.println("<" + localName + ">");
    }

    @Override
    public void characters(char[] ch, int start, int length)
            throws SAXException {

        System.out.print("characters  :");
        for(int i = 0; i < mLevel; i++) System.out.print(" ");
        System.out.print("[");
        for (int i = 0; i < length; i++) {
          System.out.print(ch[start + i]);
        }
        System.out.println("]");
    }
}

 こんな感じのクラスをつくってみた。 各関数で取得できた情報をそのままprint出力するだけの処理です。
 ハンドリング予定のstartElement()、 endElement()、characters()だけ実装してみた。
 startElement()/endElement()はに相当、characters()はwebブラウザで表示させたときに実際に画面に表示される部分に相当します。

 このコードを実行すると…、おおお、ちゃんと各要素内容が表示されました。 
 後は、取得したい情報の条件を元のHTMLから導き出せば必要な情報のみを抜き出せるって寸法ですね。

 まずは、駅名検索をして駅リストを表示するとこらへんから手をつけてみるかな。
 こういう処理よりも、Androidへの実装のほうが手がかかったりしてるのですんなりいくかどうかは不明ですけどね~。

テーマ:スマートフォン - ジャンル:携帯電話・PHS

ブログランキング・にほんブログ村へ

2011.06.11 | Comments(0) | Trackback(0) | Android

«  | HOME |  »

FC2Ad

10 | 2017/11 [GO]| 12
- - - 1 2 3 4
5 6 7 8 9 10 11
12 13 14 15 16 17 18
19 20 21 22 23 24 25
26 27 28 29 30 - -

最近の記事一覧 カテゴリ一覧 コメント一覧 トラックバック一覧 プロフィール リンク一覧
[カテゴリ]
WEBコンサルティング・ホームページ制作のバンブーウエイブ

ブログ内検索

ブロとも申請フォーム

この人とブロともになる

カスタム検索

上記広告は1ヶ月以上更新のないブログに表示されています。新しい記事を書くことで広告を消せます。