Web サイト (またはページ) を「スキャン」して情報を取得し、プログラムに取り込むにはどうすればよいですか?

StackOverflow https://stackoverflow.com/questions/2835505

  •  26-09-2019
  •  | 
  •  

質問

そうですね、私は Web ページから情報を取得して、それを自分のプログラム (Java で) に取り込む方法を理解しようとしています。

たとえば、情報が必要な正確なページ (わかりやすくするために Best Buy の商品ページ) がわかっている場合、そのページから必要な適切な情報を取得するにはどうすればよいでしょうか?タイトル、価格、説明が気に入りましたか?

このプロセスは何と呼ばれるのでしょうか?私はこれを研究し始めることさえ思いつきませんでした。

編集:さて、JSoup (BalusC によって投稿されたもの) のテストを実行していますが、次のエラーが発生し続けます。

Exception in thread "main" java.lang.NoSuchMethodError: java.util.LinkedList.peekFirst()Ljava/lang/Object;
at org.jsoup.parser.TokenQueue.consumeWord(TokenQueue.java:209)
at org.jsoup.parser.Parser.parseStartTag(Parser.java:117)
at org.jsoup.parser.Parser.parse(Parser.java:76)
at org.jsoup.parser.Parser.parse(Parser.java:51)
at org.jsoup.Jsoup.parse(Jsoup.java:28)
at org.jsoup.Jsoup.parse(Jsoup.java:56)
at test.main(test.java:12)

Apache Commons はあります

役に立ちましたか?

解決

次のような HTML パーサーを使用します ジースープ. 。これは私の好みより上です Java で使用できる他の HTML パーサー それ以来 サポートします jQuery のように CSSセレクター. 。また、ノードのリストを表すクラス、 Elements, 、実装します Iterable これを繰り返し実行できるようにするため、 拡張された for ループ (したがって、冗長で面倒な作業をする必要はありません) Node そして NodeList 平均的な Java DOM パーサーのクラスと同様です)。

これは基本的なキックオフの例です ( 最新の Jsoup JAR ファイル クラスパス内):

package com.stackoverflow.q2835505;

import org.jsoup.Jsoup;
import org.jsoup.nodes.Document;
import org.jsoup.nodes.Element;
import org.jsoup.select.Elements;

public class Test {

    public static void main(String[] args) throws Exception {
        String url = "https://stackoverflow.com/questions/2835505";
        Document document = Jsoup.connect(url).get();

        String question = document.select("#question .post-text").text();
        System.out.println("Question: " + question);

        Elements answerers = document.select("#answers .user-details a");
        for (Element answerer : answerers) {
            System.out.println("Answerer: " + answerer.text());
        }
    }

}

ご想像のとおり、これにより、あなた自身の質問とすべての回答者の名前が出力されます。

他のヒント

このは、画面スクレイピングと呼ばれ、ウィキペディアは、より具体的なウェブこするの上でこの記事を持っています。いくつかの醜い、混乱アップ、壊れ-IF-する非ブラウザ賢HTMLそこに、そう幸運がありますので、それは大きな挑戦することができます。

私は JTidy に使用します - それはJSoupにsimlarですが、私はよくJSoupを知りません。 JTidyハンドルは、HTMLが壊れ、あなたがあなたが本当にに興味のあるコンテンツを抽出するために、XSLTへのソースとしてこれを使用することができますので、W3Cの文書を返します。あなたがXSLTを知らない場合は、あなたが同様に文書として、JSoupに行くかもしれませんモデルは、W3Cよりとの仕事に進歩しています。

EDIT:JSoupウェブサイトのショーで簡単に見JSoupは確かに良い選択であってもよいです。ドキュメントからのものを抽出するためのボックスアウトCSSセレクタをサポートしているようです。これは、XSLTに入るよりも、との仕事に多くの方が簡単かもしれません。

HTML パーサーを使用することもできます (多くの便利なリンクがここにあります: Java HTMLパーサー).

このプロセスは「Web サイトのコンテンツの取得」と呼ばれます。さらに調査するには、「Web サイトのコンテンツの取得 Java」を検索してください。

jsoupのサポートするJava 1.5

https://github.com/tburch/jsoup/commit/d8ea84f46e009a7f144ee414a9fa73ea187019a3する

そのスタックのように見えますがバグだった、と修正されました。

JSoupソリューションは素晴らしいですが、あなたが本当に簡単なだけで何かを抽出する必要がある場合には、正規表現またはString.indexOfを使用する方が簡単な場合があります。

他の人がすでに述べたように、プロセスをこすると呼ばれている。

あなたはおそらく、あなたがユニークで、あなたのテキストの近くにある文字列を見つけることができれば、その後、あなたがデータを取得する行/文字-オフセットを使用することができます参照してHTMLを見てみたいと思います。

C#でSystem.XML.Linqで見つかったものと同様の任意のXMLクラスが存在しない場合は、Javaで厄介なのだろう。

また、試みることができる jARVESTするます。

これは、クモ-こすり-変換のウェブサイトへの純粋なJavaエンジン上でJRubyのDSLに基づいています。

Webページ(wgetxpathがjARVESTの言語の構築物で)内のすべてのリンクを検索

wget | xpath('//a/@href')

Javaプログラム内部ます:

Jarvest jarvest = new Jarvest();
  String[] results = jarvest.exec(
    "wget | xpath('//a/@href')", //robot! 
    "http://www.google.com" //inputs
  );
  for (String s : results){
    System.out.println(s);
  }

私の答えは、おそらくこの質問のライターに有用ではないだろう(私は推測する右のタイミングが遅いので、8ヶ月ないです)が、私はそれはおそらく、この答えに遭遇するかもしれない他の多くの開発者にとって有用であろうと思います。

今日、私はちょうどあなたは、単にいくつかの注釈を任意のPOJOクラスにHTMLをマップするために使用できることをPOJOの完全なフレームワークに(私の会社の名前で)HTMLリリース。ライブラリ自体は非常に便利であり、すべての非常にプラグイン可能でありながら、他の多くのものを提供しています。あなたは右ここに見ることができます: https://github.com/whimtrip/jwht-htmltopojo

使用方法:基礎

想像し、我々は次のHTMLページを解析する必要があります:

<html>
    <head>
        <title>A Simple HTML Document</title>
    </head>
    <body>
        <div class="restaurant">
            <h1>A la bonne Franquette</h1>
            <p>French cuisine restaurant for gourmet of fellow french people</p>
            <div class="location">
                <p>in <span>London</span></p>
            </div>
            <p>Restaurant n*18,190. Ranked 113 out of 1,550 restaurants</p>  
            <div class="meals">
                <div class="meal">
                    <p>Veal Cutlet</p>
                    <p rating-color="green">4.5/5 stars</p>
                    <p>Chef Mr. Frenchie</p>
                </div>

                <div class="meal">
                    <p>Ratatouille</p>
                    <p rating-color="orange">3.6/5 stars</p>
                    <p>Chef Mr. Frenchie and Mme. French-Cuisine</p>
                </div>

            </div> 
        </div>    
    </body>
</html>

レッツは、我々はそれをマップするPOJOを作成します

public class Restaurant {

    @Selector( value = "div.restaurant > h1")
    private String name;

    @Selector( value = "div.restaurant > p:nth-child(2)")
    private String description;

    @Selector( value = "div.restaurant > div:nth-child(3) > p > span")    
    private String location;    

    @Selector( 
        value = "div.restaurant > p:nth-child(4)"
        format = "^Restaurant n\*([0-9,]+). Ranked ([0-9,]+) out of ([0-9,]+) restaurants$",
        indexForRegexPattern = 1,
        useDeserializer = true,
        deserializer = ReplacerDeserializer.class,
        preConvert = true,
        postConvert = false
    )
    // so that the number becomes a valid number as they are shown in this format : 18,190
    @ReplaceWith(value = ",", with = "")
    private Long id;

    @Selector( 
        value = "div.restaurant > p:nth-child(4)"
        format = "^Restaurant n\*([0-9,]+). Ranked ([0-9,]+) out of ([0-9,]+) restaurants$",
        // This time, we want the second regex group and not the first one anymore
        indexForRegexPattern = 2,
        useDeserializer = true,
        deserializer = ReplacerDeserializer.class,
        preConvert = true,
        postConvert = false
    )
    // so that the number becomes a valid number as they are shown in this format : 18,190
    @ReplaceWith(value = ",", with = "")
    private Integer rank;

    @Selector(value = ".meal")    
    private List<Meal> meals;

    // getters and setters

}

そして今Mealクラスのほかます:

public class Meal {

    @Selector(value = "p:nth-child(1)")
    private String name;

    @Selector(
        value = "p:nth-child(2)",
        format = "^([0-9.]+)\/5 stars$",
        indexForRegexPattern = 1
    )
    private Float stars;

    @Selector(
        value = "p:nth-child(2)",
        // rating-color custom attribute can be used as well
        attr = "rating-color"
    )
    private String ratingColor;

    @Selector(
        value = "p:nth-child(3)"
    )
    private String chefs;

    // getters and setters.
}

私たちはgithubのページで上記のコードにいくつかのより多くの説明を提供します。

一瞬のために、のは、これをスクラップする方法を見てみましょう。

private static final String MY_HTML_FILE = "my-html-file.html";

public static void main(String[] args) {


    HtmlToPojoEngine htmlToPojoEngine = HtmlToPojoEngine.create();

    HtmlAdapter<Restaurant> adapter = htmlToPojoEngine.adapter(Restaurant.class);

    // If they were several restaurants in the same page, 
    // you would need to create a parent POJO containing
    // a list of Restaurants as shown with the meals here
    Restaurant restaurant = adapter.fromHtml(getHtmlBody());

    // That's it, do some magic now!

}


private static String getHtmlBody() throws IOException {
    byte[] encoded = Files.readAllBytes(Paths.get(MY_HTML_FILE));
    return new String(encoded, Charset.forName("UTF-8"));

}

もう一つの簡単な例を見つけることができますここ

・ホープ、この意志のヘルプ誰かそこに!

cURLのライブラリに

を見てください。私はJavaでそれを使用したことがありませんが、私はそれのためにバインディングがなければならないと確信しています。基本的に、何をやることは、あなたが「こすり」に好きなページへのcURLリクエストを送信します。要求は、ページのソースコードで文字列を返します。そこから、あなたがソースコードから好きなデータを解析するために正規表現を使用します。それはあなたがそれをどうするつもりですか一般的です。

ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top