Webエンジニアの開発記

Webエンジニアの開発記録です。Java,SAStruts,jQuery,AmazonWebService,マッシュアップ。

JavaでJTidy + XPathを使ってAタグのhref属性を取得してみた。

参考文献から。

・まずはXPathクラスのAPI

javax.xml.xpath (Java Platform SE 6)

 

・↓↓IBMXPathの解説

Java XPath API

いかにXPathを使わないとなると、DOMの解析が面倒か分かる。

未だにうちの現場では面倒な方法でDOMの解析をしていた。

あーやれやれ。

 

XPathの書き方はこちら

Java 入門 | XPath

ここも整然としていてGood。

 

今日ははてなブログ(当ブログ)の発リンクのリンク先を取得しました。

 

DOMの構築はJTidyを使った。

JTidyでパースしないと、DOM構築時にExceptionが出てしまうから。

 

下記のようなメソッドを作った。

HTTPレスポンスをそのまま渡せばDOMを構築してくれる。
    /**
     * DOM構築
     * @param inputStream HTTPレスポンスをそのまま
     * @return Document 構築されたDOM
     */
    private Document parseDomByTidy(InputStream inputStream) {

        Tidy tidy = new Tidy();
        tidy.setQuiet(true);
        tidy.setShowWarnings(false);
        tidy.setForceOutput(false);
        return tidy.parseDOM(inputStream, null);
    }

 

構築したDOMに対して、XPathでAタグのhrefをNodeListとして取得した。

NodeListはfor文で回して、Node#getNodeValue()でリンク先を取得した。


        try {
            // DOM構築
            Document document = this.parseDomByTidy(inputStream);

            // Xpath作成
            XPath xpath = XPathFactory.newInstance().newXPath();

            // ノードリスト取得
            NodeList nodeList = (NodeList) xpath.evaluate(
                    "//a/@href", document, XPathConstants.NODESET);

            // 1回目:各ノード内容表示
            System.out.println("aタグの数:" + nodeList.getLength());
            for (int i = 0; i < nodeList.getLength(); i++) {

                Node aTagNode = nodeList.item(i);
                System.out.println(aTagNode.getNodeValue());
            }

            // ノードリスト取得
            System.out.println("★<h1>タグ内の<a>タグを抽出★");
            nodeList = (NodeList) xpath.evaluate(
                    "//h1/a/@href", document, XPathConstants.NODESET);

            // 2回目:各ノード内容表示
            System.out.println("aタグの数:" + nodeList.getLength());
            for (int i = 0; i < nodeList.getLength(); i++) {

                Node aTagNode = nodeList.item(i);
                System.out.println(aTagNode.getNodeValue());
            }


        } finally {
            inputStream.close();
        }

 

実行結果(コンソール)は↓↓


line 119 column 9 - Error: <header> is not recognized!
line 147 column 17 - Error: <article> is not recognized!
line 149 column 5 - Error: <header> is not recognized!
line 152 column 12 - Error: <time> is not recognized!
aタグの数:97
#
http://noric0124.hatenablog.jp/
http://noric0124.hatenablog.jp/entries/2013/12/18
http://noric0124.hatenablog.jp/entry/2013/12/18/%E3%83%A4%E3%83%95%E3%83%BC%E3%82%88%E3%82%8A%E3%82%82%E7%B0%A1%E5%8D%98%E3%81%AAHTML%E3%82%92JTidy%E3%81%A7DOM%E8%A7%A3%E6%9E%90%E3%80%82
http://www.html-cool.com/samples/tryhtml_basic.html
http://www.html-cool.com/samples/tryhtml_basic.html
http://noric0124.hatenablog.jp/entry/2013/12/18/%E3%83%A4%E3%83%95%E3%83%BC%E3%82%88%E3%82%8A%E3%82%82%E7%B0%A1%E5%8D%98%E3%81%AAHTML%E3%82%92JTidy%E3%81%A7DOM%E8%A7%A3%E6%9E%90%E3%80%82
http://blog.hatena.ne.jp/guide/pro
http://noric0124.hatenablog.jp/entries/2013/12/18
http://noric0124.hatenablog.jp/entry/2013/12/18/JTidy%E3%81%AFSAX%E3%81%98%E3%82%83%E3%81%AA%E3%81%8F%E3%81%A6DOM
http://sourceforge.jp/projects/sfnet_jtidy/
http://d.hatena.ne.jp/keyword/Google%CB%DD%CC%F5
http://d.hatena.ne.jp/keyword/Java
http://d.hatena.ne.jp/keyword/Java
http://noric0124.hatenablog.jp/entry/2013/12/18/JTidy%E3%81%AFSAX%E3%81%98%E3%82%83%E3%81%AA%E3%81%8F%E3%81%A6DOM
http://noric0124.hatenablog.jp/entries/2013/12/18
http://noric0124.hatenablog.jp/entry/2013/12/18/DOM%E3%81%A8SAX%E3%81%AF%E9%81%95%E3%81%86%E3%80%82
http://d.hatena.ne.jp/keyword/%A5%B9%A5%AF%A5%EC%A5%A4%A5%D4%A5%F3%A5%B0
http://www.atmarkit.co.jp/ait/articles/0208/20/news002.html
http://d.hatena.ne.jp/keyword/XML
http://d.hatena.ne.jp/keyword/API
http://d.hatena.ne.jp/keyword/%A5%C7%A5%D5%A5%A1%A5%AF%A5%C8%A5%B9%A5%BF%A5%F3%A5%C0%A1%BC%A5%C9
http://d.hatena.ne.jp/keyword/Document%20Object%20Model
http://d.hatena.ne.jp/keyword/API
http://d.hatena.ne.jp/keyword/API
http://d.hatena.ne.jp/keyword/XML
http://d.hatena.ne.jp/keyword/API
http://d.hatena.ne.jp/keyword/XML
http://d.hatena.ne.jp/keyword/%B9%BD%CA%B8%B2%F2%C0%CF
http://d.hatena.ne.jp/keyword/XML
http://d.hatena.ne.jp/keyword/XML
http://d.hatena.ne.jp/keyword/XML
http://d.hatena.ne.jp/keyword/%A5%B9%A5%AF%A5%EC%A5%A4%A5%D4%A5%F3%A5%B0
http://d.hatena.ne.jp/keyword/XML
http://d.hatena.ne.jp/keyword/XPath
http://d.hatena.ne.jp/keyword/XQuery
http://noric0124.hatenablog.jp/entry/2013/12/18/DOM%E3%81%A8SAX%E3%81%AF%E9%81%95%E3%81%86%E3%80%82
http://noric0124.hatenablog.jp/entries/2013/12/17
http://noric0124.hatenablog.jp/entry/2013/12/17/JTidy%E3%82%92%E4%BD%BF%E3%81%88%E3%81%B0DOM%E3%81%8C%E6%A7%8B%E7%AF%89%E3%81%A7%E3%81%8D%E3%82%8B%E3%82%89%E3%81%97%E3%81%84%E3%80%82
http://d.hatena.ne.jp/keyword/%A4%CF%A4%C6%A4%CA%A5%D6%A5%ED%A5%B0
http://d.hatena.ne.jp/keyword/XML
http://d.hatena.ne.jp/keyword/IBM
http://d.hatena.ne.jp/keyword/IBM
http://www.ibm.com/developerworks/jp/java/library/j-jtp03225/
http://d.hatena.ne.jp/keyword/XML
http://d.hatena.ne.jp/keyword/XML
http://d.hatena.ne.jp/keyword/XPath
http://sourceforge.jp/projects/sfnet_jtidy/
http://d.hatena.ne.jp/keyword/IBM
http://noric0124.hatenablog.jp/entry/2013/12/17/JTidy%E3%82%92%E4%BD%BF%E3%81%88%E3%81%B0DOM%E3%81%8C%E6%A7%8B%E7%AF%89%E3%81%A7%E3%81%8D%E3%82%8B%E3%82%89%E3%81%97%E3%81%84%E3%80%82
http://noric0124.hatenablog.jp/entries/2013/12/15
http://noric0124.hatenablog.jp/entry/2013/12/15/%E3%83%A4%E3%83%95%E3%83%BC%E3%82%82DOM%E8%A7%A3%E6%9E%90%E3%81%97%E3%82%88%E3%81%86%E3%81%A8%E3%81%97%E3%81%9F%E3%82%89%E3%80%81SAXParseException%E3%80%82
http://d.hatena.ne.jp/keyword/%A4%CF%A4%C6%A4%CA%A5%D6%A5%ED%A5%B0
http://d.hatena.ne.jp/keyword/%A5%B9%A5%AF%A5%EC%A5%A4%A5%D4%A5%F3%A5%B0
http://noric0124.hatenablog.jp/entry/2013/12/15/%E3%83%A4%E3%83%95%E3%83%BC%E3%82%82DOM%E8%A7%A3%E6%9E%90%E3%81%97%E3%82%88%E3%81%86%E3%81%A8%E3%81%97%E3%81%9F%E3%82%89%E3%80%81SAXParseException%E3%80%82
http://noric0124.hatenablog.jp/entries/2013/12/15
http://noric0124.hatenablog.jp/entry/2013/12/15/%E3%81%AF%E3%81%A6%E3%81%AA%E3%83%96%E3%83%AD%E3%82%B0%E3%82%92DOM%E8%A7%A3%E6%9E%90%E3%81%97%E3%82%88%E3%81%86%E3%81%A8%E3%81%97%E3%81%9F%E3%82%89%E3%80%81SAXParseException%E3%80%82
http://d.hatena.ne.jp/keyword/%A4%CF%A4%C6%A4%CA%A5%D6%A5%ED%A5%B0
http://d.hatena.ne.jp/keyword/XML
http://d.hatena.ne.jp/keyword/IBM
http://www.ibm.com/developerworks/jp/xml/library/x-saxerror.html
http://d.hatena.ne.jp/keyword/%A4%CF%A4%C6%A4%CA%A5%D6%A5%ED%A5%B0
http://d.hatena.ne.jp/keyword/XML
http://noric0124.hatenablog.jp/entry/2013/12/15/%E3%81%AF%E3%81%A6%E3%81%AA%E3%83%96%E3%83%AD%E3%82%B0%E3%82%92DOM%E8%A7%A3%E6%9E%90%E3%81%97%E3%82%88%E3%81%86%E3%81%A8%E3%81%97%E3%81%9F%E3%82%89%E3%80%81SAXParseException%E3%80%82
http://noric0124.hatenablog.jp/entries/2013/12/13
http://noric0124.hatenablog.jp/entry/2013/12/13/XML%E8%A7%A3%E6%9E%90%E3%81%A7%E3%81%AF%E3%80%81%E7%B5%B6%E5%AF%BE%E3%81%ABXPath%E3%82%92%E4%BD%BF%E3%81%84%E3%81%9F%E3%81%84%E3%80%82
http://d.hatena.ne.jp/keyword/XPath
http://d.hatena.ne.jp/keyword/W3C
http://d.hatena.ne.jp/keyword/XML
http://d.hatena.ne.jp/keyword/%A5%B9%A5%AF%A5%EC%A5%A4%A5%D4%A5%F3%A5%B0
http://d.hatena.ne.jp/keyword/XPath
http://d.hatena.ne.jp/keyword/XML
http://d.hatena.ne.jp/keyword/XPath
http://d.hatena.ne.jp/keyword/XPath
http://d.hatena.ne.jp/keyword/XPath
http://d.hatena.ne.jp/keyword/XML
http://d.hatena.ne.jp/keyword/XPath
http://ja.wikipedia.org/wiki/XML_Path_Language
http://www.techscore.com/tech/XML/XPath/XPath1/xpath01.html/
http://noric0124.hatenablog.jp/entry/2013/12/13/XML%E8%A7%A3%E6%9E%90%E3%81%A7%E3%81%AF%E3%80%81%E7%B5%B6%E5%AF%BE%E3%81%ABXPath%E3%82%92%E4%BD%BF%E3%81%84%E3%81%9F%E3%81%84%E3%80%82
http://noric0124.hatenablog.jp/?page=1386946668
http://noric0124.hatenablog.jp/about
http://noric0124.hatenablog.jp/about
#
http://hatenablog.com/
http://blog.hatena.ne.jp/register?via=200109
http://staff.hatenablog.com/
http://noric0124.hatenablog.jp/archive
http://noric0124.hatenablog.jp/entry/2013/12/18/%E3%83%A4%E3%83%95%E3%83%BC%E3%82%88%E3%82%8A%E3%82%82%E7%B0%A1%E5%8D%98%E3%81%AAHTML%E3%82%92JTidy%E3%81%A7DOM%E8%A7%A3%E6%9E%90%E3%80%82
http://noric0124.hatenablog.jp/entry/2013/12/18/JTidy%E3%81%AFSAX%E3%81%98%E3%82%83%E3%81%AA%E3%81%8F%E3%81%A6DOM
http://noric0124.hatenablog.jp/entry/2013/12/18/DOM%E3%81%A8SAX%E3%81%AF%E9%81%95%E3%81%86%E3%80%82
http://noric0124.hatenablog.jp/entry/2013/12/17/JTidy%E3%82%92%E4%BD%BF%E3%81%88%E3%81%B0DOM%E3%81%8C%E6%A7%8B%E7%AF%89%E3%81%A7%E3%81%8D%E3%82%8B%E3%82%89%E3%81%97%E3%81%84%E3%80%82
http://noric0124.hatenablog.jp/entry/2013/12/15/%E3%83%A4%E3%83%95%E3%83%BC%E3%82%82DOM%E8%A7%A3%E6%9E%90%E3%81%97%E3%82%88%E3%81%86%E3%81%A8%E3%81%97%E3%81%9F%E3%82%89%E3%80%81SAXParseException%E3%80%82
http://noric0124.hatenablog.jp/archive
http://noric0124.hatenablog.jp/about
http://hatenablog.com/
http://d.hatena.ne.jp/

<h1>タグ内の<a>タグを抽出★
aタグの数:8
http://noric0124.hatenablog.jp/
http://noric0124.hatenablog.jp/entry/2013/12/18/%E3%83%A4%E3%83%95%E3%83%BC%E3%82%88%E3%82%8A%E3%82%82%E7%B0%A1%E5%8D%98%E3%81%AAHTML%E3%82%92JTidy%E3%81%A7DOM%E8%A7%A3%E6%9E%90%E3%80%82
http://noric0124.hatenablog.jp/entry/2013/12/18/JTidy%E3%81%AFSAX%E3%81%98%E3%82%83%E3%81%AA%E3%81%8F%E3%81%A6DOM
http://noric0124.hatenablog.jp/entry/2013/12/18/DOM%E3%81%A8SAX%E3%81%AF%E9%81%95%E3%81%86%E3%80%82
http://noric0124.hatenablog.jp/entry/2013/12/17/JTidy%E3%82%92%E4%BD%BF%E3%81%88%E3%81%B0DOM%E3%81%8C%E6%A7%8B%E7%AF%89%E3%81%A7%E3%81%8D%E3%82%8B%E3%82%89%E3%81%97%E3%81%84%E3%80%82
http://noric0124.hatenablog.jp/entry/2013/12/15/%E3%83%A4%E3%83%95%E3%83%BC%E3%82%82DOM%E8%A7%A3%E6%9E%90%E3%81%97%E3%82%88%E3%81%86%E3%81%A8%E3%81%97%E3%81%9F%E3%82%89%E3%80%81SAXParseException%E3%80%82
http://noric0124.hatenablog.jp/entry/2013/12/15/%E3%81%AF%E3%81%A6%E3%81%AA%E3%83%96%E3%83%AD%E3%82%B0%E3%82%92DOM%E8%A7%A3%E6%9E%90%E3%81%97%E3%82%88%E3%81%86%E3%81%A8%E3%81%97%E3%81%9F%E3%82%89%E3%80%81SAXParseException%E3%80%82
http://noric0124.hatenablog.jp/entry/2013/12/13/XML%E8%A7%A3%E6%9E%90%E3%81%A7%E3%81%AF%E3%80%81%E7%B5%B6%E5%AF%BE%E3%81%ABXPath%E3%82%92%E4%BD%BF%E3%81%84%E3%81%9F%E3%81%84%E3%80%82

正常終了です。
終了時刻:Thu Dec 19 00:44:34 JST 2013 

 

という結果だった。

1回目はとにかくすべてのaタグのリンク先を抜き出した。

すると97件出てきた。多すぎる。

 

2回目ではh1タグ内にあるaタグに絞って抜き出した。

すると8件。

これは各記事タイトルに相当している。

 

特に意味のあるデータではないが、

XPathの練習としてやってみたました。

 

XPathはNodeListの取得が簡単にできるので、

表記法に慣れれば相当便利です。

 

ただし、最終的にはfor文で回さないといけないのが、

どうもまだ面倒な気がしますね。

 

XQueryという、XPathの上位技術を使えば、

もっと楽になるという記事を読みました。

後々そちらにも挑戦していこうかな。