1:Jsoupとは
1: Jsoupの概要
jsoup は Java ベースの HTML パーサーであり、一連の非常に労力を節約する API を提供し、URL アドレス、HTML テキスト コンテンツを直接解析できるだけでなく、DOM、CSS、または jQuery と同様の方法でデータを操作することもできます。 Web サイトから dom 構造を取得してダウンロード データを解析するためのクローラー ツールとしても使用できます。
2: Jsoupでできること
- URL、ファイル、または文字列から HTML をスクレイピングして解析する (クローラー)
- DOM トラバーサルまたは CSS セレクターを使用してデータを検索および抽出する
- HTML 要素、属性、およびテキストを操作する
- ユーザーが送信したコンテンツをセーフリストに照らしてサニタイズし、XSS 攻撃を防ぎます
- きれいなページを出力する
2: Jsoup 関連の概念
Jsoup の多くの概念は js に似ています。理解のために比較を参照できます。
- ドキュメント: ドキュメント オブジェクト。各 HTML ページはドキュメント オブジェクトであり、Document は jsoup システムの最上位の構造です。
- Element : 要素オブジェクト。Document には複数の Element オブジェクトを含めることができ、Element オブジェクトを使用してノードを走査し、データを抽出したり、HTML を直接操作したりできます。
- Elements : List に似た要素オブジェクトのコレクション。
- ノード: ノード オブジェクト。ラベル名、属性などはすべてノード オブジェクトであり、ノード オブジェクトはデータの格納に使用されます。
- クラスの継承関係: Document は Element を継承し ( class Document extends Element )、 Element は Node を継承します ( class Element extends Node )。
- 一般的な実行フロー: 最初に Document オブジェクトを取得し、次に Element オブジェクトを取得し、最後に Node オブジェクトを介してデータを取得します。
3: ドキュメントを入手する
1: jsoupのjarパッケージをインポートする
<!-- jsoup -->
<dependency>
<groupId>org.jsoup</groupId>
<artifactId>jsoup</artifactId>
<version>1.11.3</version>
</dependency>
2: URL からドキュメント オブジェクトを読み込む (一般的に使用されます)
Jsoup.connect(String url).get() メソッドを使用して取得します (http および https プロトコルのみがサポートされています)。
try {
Document document = Jsoup.connect("http://www.baidu.com").get();
System.out.println(document.title());
} catch (IOException e) {
throw new RuntimeException(e);
}
- connect(String url) メソッドは、新しい接続を作成し、.get() または .post() メソッドを介してデータを取得します。この URL から HTML を取得中にエラーが発生した場合、IOException がスローされ、適切に処理する必要があります。
- Connection インターフェイスは、特別なリクエストを解決するためのメソッド チェーンも提供します。次のように、リクエストを送信するときに、リクエストのヘッダー パラメータを取得できます。
try {
Document document = Jsoup.connect("http://www.baidu.com")
.data("query", "Java")
.userAgent("Mozilla")
.cookie("auth", "token")
.timeout(8000)
.post();
System.out.println(document);
} catch (IOException e) {
throw new RuntimeException(e);
}
3: ローカル ファイルからドキュメント オブジェクトを読み込む
ドキュメントは、静的な Jsoup.parse(File in, String charsetName) メソッドを使用してファイルからロードできます。in はパスを表し、charsetName はエンコード方法を表します。サンプル コード:
File input = new File("/tmp/input.html");
Document doc = Jsoup.parse(input, "UTF-8");
System.out.println(doc);
4: 文字列リテラルから文書オブジェクトを読み込む
静的な Jsoup.parse(String html) メソッドを使用して、文字列テキストからドキュメント オブジェクト Document を取得します。サンプル コード:
String html = "<html><head><title>First parse</title></head>"
+ "<body><p>Parsed HTML into a doc.</p></body></html>";
Document doc = Jsoup.parse(html);
System.out.println(doc);
5: フラグメントから文書オブジェクトを取得する
Jsoup.parseBodyFragment(String html) メソッドを使用する
String html = "<p>Lorem ipsum.</p>";
Document doc = Jsoup.parseBodyFragment(html);
// doc 此时为:<body> <p>Lorem ipsum.</p></body>
Element body = doc.body();
System.out.println(body);
parseBodyFragment メソッドは新しいドキュメントを作成し、解析された HTML を body 要素に挿入します。通常の Jsoup.parse(String html) メソッドを使用すると、通常は同じ結果が得られますが、ユーザー入力をボディ フラグメントとして明示的に処理する方が適切です。
Document.body() メソッドは、ドキュメントの body 要素のすべての子要素を取得できます。これは、doc.getElementsByTag("body") と同じです。
4: 選択要素の配置
1: DOM モード
dom 構造を使用して、タグ、id、クラスなどから従属要素を見つけることができます。
1: ケースコード
// 获取csdn首页所有的链接
Document doc = Jsoup.connect("http://www.baidu.com").get();
Elements elements = doc.getElementsByTag("body");
Elements contents = elements.first().getElementsByTag("a");
for (Element content : contents) {
String linkHref = content.attr("href");
String linkText = content.text();
System.out.print(linkText + "\t");
System.out.println(linkHref);
}
2: 要素を検索 - 次のメソッドは Element または Elements を返します
- getElementById(String id): ID による要素の検索
- getElementsByTag(String tag): タグによる要素の検索
- getElementsByClass(String className): クラスセレクターで要素を検索
- getElementsByAttribute(String key): href 要素を含むタグを検索するなど、属性名で要素を検索します。
- siblingElements(): 兄弟要素を取得します。要素に兄弟がない場合は空のリストを返します。
- firstElementSibling(): 最初の兄弟要素を取得します。
- lastElementSibling(): 最後の兄弟要素を取得します。
- nextElementSibling(): 次の兄弟要素を取得します。
- previousElementSibling(): 前の兄弟要素を取得します。
- parent(): このノードの親ノードを取得します。
- children(): このノードのすべての子ノードを取得します。
- child(int index): このノードの指定された子ノードを取得します。
2: CSSセレクター方式
You can also use a syntax similar to CSS selectors to find and manage elements. 一般的に使用されるメソッドは、select (文字列セレクター) です。
1: コード例
Document doc = Jsoup.connect("http://csdn.com").get();
// 获取带有 href 属性的 a 元素
Elements elements = doc.select("a[href]");
for (Element content : elements) {
String linkHref = content.attr("href");
String linkText = content.text();
System.out.print(linkText + "\t");
System.out.println(linkHref);
}
select() メソッドは、Document、Element、または Elements オブジェクトで使用でき、コンテキスト依存であるため、指定された要素のフィルタリングを実装したり、チェーン アクセスを使用したりできます。
select() メソッドは要素のコレクションを返し、結果を抽出して処理するための一連のメソッドを提供します。
2: select (文字列セレクター) メソッドのパラメーターの紹介
- tagname: < a > タグを検索するには、「a」などのタグで要素を検索します。
- #id: #logo search < p id="logo"> などの ID で要素を検索します
- .class: .titile <p class="titile"> などのクラス名で要素を検索します
- ns|tag: fb|name を使用して <fb:name> を検索するなど、名前空間内の要素をタグで検索します。
- [属性]: [href] < a href="..."> を検索するなど、属性を使用して要素を検索します。
- [ ^attribute]: 属性名のプレフィックスを使用して要素を検索します。たとえば、[^data-] を使用して HTML5 データセット属性を持つ要素を検索できます。
- [ attribute=value]: 属性値を使用して要素を検索します。例: [ width=500]
- [attribute^=value]、[attribute$=value]、[attribute*=value]: [href*=/path/] で検索するなど、属性値の先頭、末尾、または包含を照合して要素を検索します。
- [attribute~=regex]: img[src~=(?i).(png|jpe?g)] などの要素を検索するための正規表現に一致する属性値を使用して、すべての png または jpg、jpeg 形式の画像に一致させます
- *: ワイルドカード、すべての要素に一致
3: パラメータ属性の組み合わせ
例:要素 elements = doc.select(“ div.css_tr_event ”);
- el#id: 要素 + ID、例: div#logo
- el.class: 要素 + クラス。例: div.masthead
- el[attr]: a[href] などの要素 + クラスは、href 属性を持つすべての要素に一致します。
- 任意の組み合わせ。たとえば、a[href].highlight は、href 属性と class="highlight" を持つすべての要素に一致します。
- 祖先の子: 要素の子要素を検索します。たとえば、.body p を使用して、「body」要素の下にあるすべての p 要素を検索し、途中に空白を含めることができます。
- 親 > 子: 親要素の下の直接の子要素を検索します。たとえば、div.content > p を使用して p 要素を検索するか、body > * を使用して body タグの下のすべての直接の子要素を検索できます。
- siblingA + siblingB: A 要素の前にある最初の兄弟要素 B を検索します。例: div.head + div
- siblingA ~ siblingX: h1 ~ p のように、A 要素の前にある兄弟 X 要素を検索します。
- el、el、el: 複数のセレクターの組み合わせ、任意のセレクターに一致する一意の要素を検索します。例: div.masthead、div.logo
4: 特殊パラメータ: 疑似セレクタ
- :lt(n): n 未満の兄弟インデックス値 (その位置は DOM ツリー内の親ノードからの相対位置) を持つ要素を検索します。たとえば、td:lt(3) は 3 列未満の要素を意味します。
- :gt(n): n`` より大きい兄弟インデックス値を持つ要素を見つけます。例: div p:gt(2) は、どの div に 2 つ以上の p 要素が含まれているかを示します。
- :eq(n): n と同じレベル インデックス値を持つ要素を検索します。例: form input:eq(1) は、input タグを含む Form 要素を示します。
- :has(seletor): セレクターに含まれる要素と一致する要素を検索します。たとえば、div:has§ は、p 要素を含む div を示します。
- :not(selector): セレクターに一致しない要素を検索します。たとえば、div:not(.logo) は、class=logo 要素を含まないすべての div のリストを意味します。
- :contains(text): 指定されたテキストを含む要素を検索します。検索では大文字と小文字が区別されません。例: p:contains(jsoup)
- :containsOwn(text): 指定されたテキストを直接含む要素を検索します
- :matches(regex): テキストが指定された正規表現に一致する要素を検索します。例: div:matches((?i)login)
- :matchesOwn(regex): 指定された正規表現に一致するテキストを含む要素を検索します
- 注: 上記の疑似セレクターのインデックスは 0 から始まります。つまり、最初の要素のインデックス値は 0、2 番目の要素のインデックス値は 1 などです。
5: データを取得する
1: 要素データを取得する
- attr(String key): 単一の属性値を取得します
- attributes(): すべての属性値を取得します
- attr(文字列キー、文字列値): 属性値を設定
- text(): テキスト コンテンツを取得する
- text(String value): テキストの内容を設定します
- html(): 要素内の HTML コンテンツを取得します
- html(文字列値): 要素内の HTML コンテンツを設定します
- outerHtml(): 要素の外側の HTML コンテンツを取得する
- data(): データ コンテンツを取得します (例: script および style タグ)
- id(): id 値を取得します (例:
衣類
) - className(): 最初のクラス セレクタ値を取得する
- classNames(): すべてのクラス セレクタ値を取得する
- tag(): 要素タグを取得
- tagName(): 要素のタグ名を取得します (次のような:
、
待って)
2: HTML テキストを操作する
- append(String html): 最後に HTML テキストを追加します
- prepend(String html): 先頭に HTML テキストを追加します
- html(文字列値): 一致した要素内に HTML テキストを追加します。
6: データを修正する
Document オブジェクトを解析した後、その属性値の一部を変更して、それをフロント ページに出力したり、他の場所に保存したりすることができます. jsoup は、このための非常に便利なインターフェイスを提供します (チェーン書き込みをサポートします).
1: 属性の値を設定します
次のメソッドが Element オブジェクトで動作する場合、1 つの要素のみが影響を受けます。Elements オブジェクトを操作すると、複数の要素が影響を受ける場合があります。
- .attr(String key, String value): ラベルの属性値を設定します。
- .addClass(String className): クラスセレクターオプションを追加
- .removeClass(String className): 対応するクラス セレクターを削除します
Document doc = Jsoup.connect("http://csdn.com").get();
// 复数,Elements
Elements elements = doc.getElementsByClass("text");
// 单数,Element
Element element = elements.first();
// 复数对象,所有 class="text" 的元素都将受到影响
elements.attr("name","goods");
// 单数对象,只有一个元素会受到影响(链式写法)
element.attr("name","shop")
.addClass("red");
2: 要素の HTML コンテンツを変更する
次のように、Element で HTML 設定メソッドを使用できます。
- .html(文字列値): このメソッドは、最初に要素内の HTML コンテンツをクリアしてから、受信した HTML に置き換えます。
- .prepend(文字列値): 要素の前に html コンテンツを追加します。
- .append(文字列値): 要素の後に html コンテンツを追加します。
- .wrap(文字列値): 外部 HTML コンテンツを要素にラップし、新しく追加されたコンテンツの中央に要素を配置します。
Document doc = Jsoup.connect("http://csdn.com").get();
Element div = doc.select("div").first();
div.html("<p>csdn</p>");
div.prepend("<p>a</p>");
div.append("<p>good</p>");
// 输出:<div"> <p>a</p> <p>csdn</p> <p>good</p> </div>
Element span = doc.select("span").first();
span.wrap("<li><a href='...'></a></li>");
// 输出: <li><a href="..."> <span>csdn</span> </a></li>
3: 要素のテキスト コンテンツを変更する
入力テキストに <、> などの文字が含まれている場合、HTML ではなくテキストとして処理されます。
- .text(String text) : 要素内の HTML コンテンツをクリアし、提供されたテキストに置き換えます。
- .prepend(String first): 要素の後にテキスト ノードを追加します。
- Element.append(String last): 要素の前にテキスト ノードを追加します。
// <div></div>
Element div = doc.select("div").first();
div.text(" one ");
div.prepend(" two ");
div.append(" three ");
// 输出: <div> two one three </div>
7: その他の機能
1: html リンクの絶対パスを返す
問題の説明:
相対 URL パスを含む HTML ドキュメントがあり、これらの相対パスを絶対パスを含む URL に変換する必要があります。
解決:
ドキュメントを解析するときは、必ずベース URI パスを指定してください。
次に、abs: 属性プレフィックスを使用して、ベース URI を含む絶対パスを取得します。コードは以下のように表示されます:
Document doc = Jsoup.connect("http://www.open-open.com").get();
Element link = doc.select("a").first();
// 输出:/
String relHref = link.attr("href");
// 输出:http://www.open-open.com/
String absHref = link.attr("abs:href");
説明します:
HTML 要素では、URL は多くの場合、ドキュメントの場所に対する相対パス ( ...など) として記述されます。.attr(String key) メソッドを使用して要素の href 属性を取得すると、HTML ソース コードで指定された値が直接返されます。
絶対パスを取得する必要がある場合は、ルート パス attr("abs:href") を含む URL アドレスを返すことができるように、属性名の前に abs: プレフィックスを追加する必要があります。したがって、HTML ドキュメントを解析するときは、ベース URI を定義することが非常に重要です。
2: プロキシを使用する
特定の Web ページにアクセスするためにプロキシ サーバーを使用する必要がある場合、この方法を使用してプロキシを設定できます。後続の要素操作は同じです。
Document document = Jsoup.connect("http://csdn.net/")
.proxy("12.12.12.12", 1080) // 使用代理
.get();