27

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

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

使うべきか

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

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

4

6 に答える 6

47

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

したがって、最速とは、最も便利で読みやすく、保守しやすいコードを意味すると仮定すると、 a を使用しDocumentBuilderて関連する HTML を解析し、XPathExpressionsを使用してデータを抽出することをお勧めします。

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")..)、必要に応じて残りの HTML エラーをString操作で修正してから解析することをお勧めします。ただし、これが複雑すぎる場合 (つまり、HTMLが非常に悪い場合) は、他の回答で提案されているように、ハッキーなパターン マッチング アプローチを使用してください。

備考

  • XPath は API レベル 8 (Android 2.2) 以降で使用できます。下位の API レベル向けに開発する場合は、DOM メソッドと条件を使用して、抽出するノードに移動できます。
于 2010-06-20T21:51:54.373 に答える
19

最速の方法は、特定の情報を自分で解析することです。HTMLの構造を事前に正確に知っているようです。、およびメソッドで十分ですBufferedReader。あなた自身の質問の最初の段落を表示するキックオフの例を次に示します。StringStringBuilder

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 をコメントに投稿してください。その方法を提案します。

于 2010-06-18T15:20:26.940 に答える
2

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

正規表現を使用することは、すべての人に好まれるわけではありません。実行時に論理例外が発生するためです。

Html パーサーの使用は、より複雑です。適切な出力が得られるかどうかはわかりません。私の経験では、あまりにもランタイム例外が発生しました。

そのため、URL を Xml ファイルに応答するようにするとよいでしょう。xml の解析は非常に簡単で効果的です。

于 2010-06-19T11:54:28.677 に答える
1

なぜあなたはちょうど書かないのですか

int start=data.indexOf("説明");

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

于 2010-06-15T23:42:34.497 に答える
0

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

于 2010-06-04T02:59:11.580 に答える
0

これを行う 1 つの方法は、html を文字列に入れ、その文字列を手動で検索して解析することです。タグが特定の順序で来ることがわかっている場合は、それをクロールしてデータを見つけることができるはずです。ただし、これはちょっとずさんなので、今すぐ機能させたいですか?またはうまく動作しますか?

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 回だけ実行し、それを機能させる必要がある場合は、これでうまくいく可能性があります。

于 2010-06-04T04:30:30.570 に答える