web-dev-qa-db-ja.com

AndroidでHTML Webページをスクレイピングする最速の方法は何ですか?

Androidの非構造化Webページから情報を抽出する必要があります。必要な情報は、idを持たないテーブルに埋め込まれています。

<table> 
<tr><td>Description</td><td></td><td>I want this field next to the description cell</td></tr> 
</table>

使用すべきですか

  • パターンマッチング?
  • BufferedReaderを使用して情報を抽出しますか?

または、その情報を取得するより速い方法はありますか?

25
unj2

この場合、パフォーマンスの違いはほとんどないため、情報をextractするfast方法を探すことは意味がないと思いますHTMLをdownloadするのにかかる時間と比較すると、回答ですでに提案されている方法の間で。

fastestで最も便利で読みやすく保守可能なコードを意味すると仮定して、関連するHTMLを解析するために DocumentBuilder を使用することをお勧めします XPathExpression sを使用してデータを抽出します。

_Document doc = DocumentBuilderFactory.newInstance()
  .newDocumentBuilder().parse(new InputSource(new StringReader(html)));

XPathExpression xpath = XPathFactory.newInstance()
  .newXPath().compile("//td[text()=\"Description\"]/following-sibling::td[2]");

String result = (String) xpath.evaluate(doc, XPathConstants.STRING);
_

無効なHTMLを取得する場合は、関連する部分を分離し(例:substring(indexOf("<table")..を使用)、必要に応じて、解析前にString操作で残りのHTMLエラーを修正することをお勧めします。ただし、これがあまりにも複雑になった場合(つまり非常に悪いHTML)、他の回答で示唆されているように、ハッキングパターンマッチングアプローチを使用してください。

備考

  • XPathはAPIレベル8(Android 2.2)以降で使用可能です。より低いAPIレベル向けに開発する場合、DOMメソッドと条件を使用して、抽出するノードに移動できます。
47
Josef Pfleger

fastestの方法では、specific情報を自分で解析します。 HTML構造を事前に正確に知っているようです。 BufferedReaderString および StringBuilder メソッドで十分です。独自の質問の最初の段落を表示するキックオフの例は次のとおりです。

public static void main(String... args) throws Exception {
    URL url = new URL("http://stackoverflow.com/questions/2971155");
    BufferedReader reader = null;
    StringBuilder builder = new StringBuilder();
    try {
        reader = new BufferedReader(new InputStreamReader(url.openStream(), "UTF-8"));
        for (String line; (line = reader.readLine()) != null;) {
            builder.append(line.trim());
        }
    } finally {
        if (reader != null) try { reader.close(); } catch (IOException logOrIgnore) {}
    }

    String start = "<div class=\"post-text\"><p>";
    String end = "</p>";
    String part = builder.substring(builder.indexOf(start) + start.length());
    String question = part.substring(0, part.indexOf(end));
    System.out.println(question);
}

解析は、事実上すべての場合、パターンマッチングよりも確実に高速です。パターンマッチングは簡単ですが、確かに複雑な正規表現パターンを使用する場合、予期しない結果が生じる可能性があるという特定のリスクがあります。

また、自分で作成する代わりに、より柔軟なサードパーティのHTMLパーサーを使用することも検討できます。事前に知られている情報で自分自身を解析するほど速くはありません。ただし、より簡潔で柔軟になります。適切なHTMLパーサーでは、速度の違いはごくわずかです。これには Jsoup を強くお勧めします。 jQueryのようなCSSセレクター をサポートします。あなたの質問の最初の段落を抽出すると、次のように簡単になります:

public static void main(String... args) throws Exception {
    Document document = Jsoup.connect("http://stackoverflow.com/questions/2971155").get();
    String question = document.select("#question .post-text p").first().text();
    System.out.println(question);
}

どのWebページについて話しているのかは不明であるため、Jsoupを使用して特定のページから特定の情報を選択する方法の詳細な例を挙げることはできません。それでもJsoupと CSSセレクター を使用して自分で理解できない場合は、コメントにURLを投稿してください。その方法をお勧めします。

19
BalusC

Html webPageをスクラップするとき。できることは2つあります。最初の1つはREGEXを使用しています。もう1つはHtmlパーサーです。

正規表現を使用することは、誰にとっても好ましくありません。ランタイムで論理例外が発生するためです。

Html Parserの使用はより複雑です。適切な出力が来るかどうかはわかりません。私の経験から、それもまたランタイム例外を作りました。

そのため、XmlファイルへのURLの応答を改善する必要があります。 xml parsing を実行するのは非常に簡単で効果的です。

2
Praveen

書いてみませんか

int start = data.indexOf( "Description");

その後、必要な部分文字列を取得します。

1
Fedor

CURLと simple html dom parser でスクレイピングを行うスクリプトを作成して、そのページから必要な値を取得してみませんか?これらのツールはPHPで動作しますが、他のツールは必要な言語用に存在します。

0
Oren Hizkiya

これを行う1つの方法は、htmlをストリングに入れてから、ストリングを手動で検索および解析することです。タグが特定の順序で来ることがわかっている場合は、タグをクロールしてデータを見つけることができるはずです。しかし、これはちょっとずさんなので、それを動作させたいかどうかの質問now?または仕事well

int position = (String)html.indexOf("<table>");  //html being the String holding the html code
String field = html.substring(html.indexOf("<td>",html.indexOf("<td>",position)) + 4, html.indexOf("</td>",html.indexOf("</td>",position)));

私が言ったように...本当にずさんな。ただし、これを1回だけ実行していて、動作させる必要がある場合は、これでうまくいく可能性があります。

0
mtmurdock