私のニーズ:
-
JsoupとpanLNを学ぶ必要があります。
私はそれを次のように解決しました:
-
Jsoupドキュメントをもう一度読んでください。
-
ブログを整理する
-
公式文書:https://jsoup.org/
jsoupは、HTMLのDOMツリーを解析するために使用されます。DOMツリーの場合、JavaはHTMLとXMLの解析を解決するためのノードとドキュメントを提供します。Jsoupは、URLリクエストとローカルファイルを介したHTMLの解析など、ノードとドキュメントよりも強力な機能を提供します。
jsoup:JavaHTMLパーサー
jsoupは、実際のHTMLを処理するためのJavaライブラリです。HTML5およびCSSセレクターの最高のDOMメソッドを使用して、URLを取得し、データを抽出および処理するための非常に便利なAPIを提供します。
jsoupは、WHATWG HTML5仕様を実装し、HTMLを最新のブラウザーと同じDOMに解析します。
-
URL、ファイル、または文字列から HTMLを取得して解析します
-
プロセスの HTML要素、属性、テキスト
-
XSS攻撃を防ぐために、安全なホワイトリストに従ってユーザーから送信されたコンテンツをクリアします
-
きちんとしたHTMLを出力する
jsoupは、未加工で検証済みのタグスープから無効なタグスープまで、実際に見られるすべての種類のHTMLを処理するように設計されています。jsoupは賢明な解析ツリーを作成します。
入力値
-
文字列からドキュメントと本文のフラグメントを解析する
/** * @Author Liruilong * @Description 字符串解析文档 * @Date 15:44 2020/3/24 * 使用静态Jsoup.parse(String html)方法, * 或者Jsoup.parse(String html, String baseUri)如果页面来自网络,并且您想要获取绝对URL(请参见[使用URL])。 * <p> * 只要传入一个非null的字符串,就可以确保您成功且明智地进行了解析, * 并且Document包含(至少)一个 head和一个body元素 **/ public static void test1() { 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("获取body中的html: " + doc.body().html()); System.out.println("获取head中的文本: " + doc.head().text()); }
Jsoup.parse(String html)方法、
Jsoup.parse(String html、String baseUri) -
URLからドキュメントをロード
/** * @Author Liruilong * @Description 从URL加载文档 * @Date 15:50 2020/3/24 * 使用Jsoup.connect(String url)方法: * 该connect(String url)方法创建一个new Connection,并get()获取并解析一个HTML文件。 * 如果在提取网址时发生错误,则会抛出一个IOException,您应该适当地处理它。 * 此方法仅支持Web URL(http和https协议) * 也可以构建一个post请求 **/ public static void test2() { Document doc = null; try { doc = Jsoup.connect("https://www.baidu.com/").get(); } catch (IOException e) { e.printStackTrace(); } System.out.println(doc.title()); System.out.println(doc.body()); System.out.println(doc.head()); } /** * @return void * @Author Liruilong * @Description 构建post请求 * @Date 16:15 2020/3/24 * @Param [] **/ public static void test3() { try { Document doc = Jsoup.connect("http://example.com") .data("query", "Java") .userAgent("Mozilla") .cookie("auth", "token") .timeout(3000) .post(); } catch (IOException e) { e.printStackTrace(); } }
doc = Jsoup.connect( "https://www.baidu.com/").get();
-
ファイルからドキュメントをロードする
/** * @Author Liruilong * @Description 从文件加载文档 * @Date 16:17 2020/3/24 * 该parse(File in, String charsetName, String baseUri)方法加载并解析HTML文件。 * 如果在加载文件时发生错误,它将抛出一个IOException * baseUri解析器使用该参数在<base href>找到元素之前解析文档中的相对URL 。 * 如果您不需要,可以改为传递一个空字符串。 * 姐妹方法parse(File in, String charsetName),该方法将文件的位置用作baseUri。 * 如果您在文件系统本地站点上工作,并且它指向的相对链接也在文件系统上,则此功能很有用。 **/ public static void test4() { File input = new File("G:\\jsoupDemo\\tmp\\input.html"); try { //parse(File in, String charsetName) Document doc = Jsoup.parse(input, "UTF-8", "https://www.baidu.com/"); System.out.println(doc.head().text()); } catch (IOException e) { e.printStackTrace(); } }
ドキュメントdoc = Jsoup.parse(File in、String charsetName);
データを抽出する
-
DOMメソッドを使用してドキュメントを参照する
/** * @Author Liruilong * @Description 使用DOM方法浏览文档 * @Date 16:52 2020/3/24 * 将HTML解析为Document之后,请使用类似DOM的方法Document。 * 寻找元素: * getElementById(String id) * getElementsByTag(String tag) * getElementsByClass(String className) * getElementsByAttribute(String key) * 元素的兄弟姐妹::siblingElements(),firstElementSibling(),lastElementSibling(),nextElementSibling(),previousElementSibling() * 获取doc:parent(),children(),child(int index) * 元素数据: * attr(String key)获取和attr(String key, String value)设置属性 * attr(String key)获取和attr(String key, String value)设置属性 * attributes() 获取所有属性 * id(),className()和classNames() * text()获取并text(String value)设置文本内容 * html()获取并html(String value)设置内部HTML内容 * outerHtml() 获得外部HTML值 * data()获取数据内容(例如script和style标签) * tag() 和 tagName() * 处理HTML和文本 * append(String html), prepend(String html) * appendText(String text), prependText(String text) * appendElement(String tagName), prependElement(String tagName) * html(String value) **/ public static void test1() throws IOException { File input = new File("G:\\jsoupDemo\\tmp\\input.html"); Document doc = Jsoup.parse(input, "UTF-8"); Element content = doc.getElementById("s_wrap"); System.out.println("Iid的内容:" + content.text()); Elements links = content.getElementsByTag("li"); links.stream().forEach(o -> { System.out.println(o.attr("class").toString()); System.out.println(o.text()); }); }
getElementById(String id)
getElementsByTag(String tag)
getElementsByClass(String className)
getElementsByAttribute(String key)
………………
-
セレクター構文を使用して要素を検索する
/** * @Author Liruilong * @Description 使用选择器语法查找元素 * @Date 17:22 2020/3/24 * Element.select(String selector)和Elements.select(String selector)方法 * 该select方法在一个可用Document,Element或在Elements。它是上下文相关的, * 因此您可以通过从特定元素中进行选择或链接选择调用来进行过滤。 * 选择器概述: * tagname:按标签查找元素,例如 a * ns|tag:通过名称空间中的标签fb|name查找<fb:name>元素,例如,查找元素 * #id:按ID查找元素,例如 #logo * .class:按类名称查找元素,例如 .masthead * [attribute]:具有属性的元素,例如 [href] * [^attr]:具有属性名称前缀的[^data-]元素,例如查找具有HTML5数据集属性的元素 * [attr=value]:具有属性值的元素,例如[width=500](也可以引用,如[data-name='launch sequence']) * [attr^=value],[attr$=value],[attr*=value]:与属性的元素,与开始,结束与,或包含所述的值,例如[href*=/path/] * [attr~=regex]:具有与正则表达式匹配的属性值的元素;例如img[src~=(?i)\.(png|jpe?g)] * *:所有元素,例如 * * 选择器组合: * el#id:具有ID的元素,例如 div#logo * el.class:具有类的元素,例如 div.masthead * el[attr]:具有属性的元素,例如 a[href] * 任何组合,例如 a[href].highlight * ancestor child:从祖先派生的子元素,例如在“ body”类的块下的任何位置.body p找到p元素 * parent > child:直接从父级派生的子元素,例如div.content > pfind p元素;并body > *找到身体标签的直接子代 * siblingA + siblingB:查找紧随同级A的同级B元素,例如 div.head + div * siblingA ~ siblingX:查找同级X元素后跟同级A,例如 h1 ~ p * el, el, el:将多个选择器组合在一起,找到与任何选择器匹配的唯一元素;例如div.masthead, div.logo * 伪选择器: * :lt(n):查找其同级索引(即,它在DOM树中相对于其父级的位置)小于的元素n;例如td:lt(3) * :gt(n):查找同级索引大于的元素n; 例如div p:gt(2) * :eq(n):查找兄弟索引等于的元素n; 例如form input:eq(1) * :has(selector):查找包含与选择器匹配的元素的元素;例如div:has(p) * :not(selector):查找与选择器不匹配的元素;例如div:not(.logo) * :contains(text):查找包含给定文本的元素。搜索不区分大小写;例如p:contains(jsoup) * :containsOwn(text):查找直接包含给定文本的元素 * :matches(regex):查找文本与指定正则表达式匹配的元素;例如div:matches((?i)login) * :matchesOwn(regex):查找其自身文本与指定的正则表达式匹配的元素 * 请注意,上面索引的伪选择器基于0,即第一个元素位于索引0,第二个元素位于1,依此类推。 **/ public static void test2() throws IOException { File input = new File("G:\\jsoupDemo\\tmp\\input.html"); Document doc = Jsoup.parse(input, "UTF-8", "http://example.com/"); Elements links = doc.select("a[href]"); // a with href Elements pngs = doc.select("img[src$=.png]"); // img with src ending .png Element masthead = doc.select("div.masthead").first(); // div with class=masthead Elements resultLinks = doc.select("h3.r > a"); // direct a after h }
Element.select(文字列セレクター)
Elements.select(文字列セレクター) -
要素から属性、テキスト、HTMLを抽出します
/** * @Author Liruilong * @Description 从元素中提取属性,文本和HTML * @Date 17:32 2020/3/24 * 要获取属性的值,请使用Node.attr(String key)方法 * 对于元素(及其组合的子元素)上的文本,请使用 Element.text() * 对于HTML,请使用Element.html(),或Node.outerHtml()酌情使用 * Element.id() * Element.tagName() * Element.className() 和 Element.hasClass(String className) **/ public static void test3() { String html = "<p>An <a href='http://example.com/'><b>example</b></a> link.</p>"; Document doc = Jsoup.parse(html); Element link = doc.select("a").first(); String text = doc.body().text(); // "An example link" String linkHref = link.attr("href"); // "http://example.com/" String linkText = link.text(); // "example"" System.out.println(text); System.out.println(linkHref); String linkOuterH = link.outerHtml(); // "<a href="http://example.com"><b>example</b></a>" String linkInnerH = link.html(); // "<b>example</b>" }
Element.html()
Node.outerHtml() -
URLを使用する
/** * @Author Liruilong * @Description 使用网址 * @Date 17:40 2020/3/24 * 您有一个包含相对URL的HTML文档,您需要将其解析为绝对URL。 * 确保base URI在解析文档时指定一个(从URL加载时是隐式的),并且 * 使用abs:属性前缀可以从属性解析绝对URL: * 在HTML元素中,通常是相对于文档的位置写URL <a href="/download">...</a>。 * 当您使用该Node.attr(String key)方法获取href属性时,将按源HTML中指定的方式返回该属性。 * 如果要获取绝对URL,则有一个属性键前缀abs:, * 它将导致根据文档的基本URI(原始位置)解析属性值:attr("abs:href") **/ public static void test4() throws IOException { Document doc = Jsoup.connect("http://jsoup.org").get(); Element link = doc.select("a").first(); String relHref = link.attr("href"); // == "/" String absHref = link.attr("abs:href"); // "http://jsoup.org/" }
-
サンプルプログラム:リストリンク
/** * @return * @Author Liruilong * @Description * @Date 17:44 2020/3/24 * @Param **/ public static void test4(String[] args) throws IOException { Validate.isTrue(args.length == 1, "usage: supply url to fetch"); String url = args[0]; print("Fetching %s...", url); Document doc = Jsoup.connect(url).get(); Elements links = doc.select("a[href]"); Elements media = doc.select("[src]"); Elements imports = doc.select("link[href]"); print("\nMedia: (%d)", media.size()); for (Element src : media) { if (src.normalName().equals("img")) print(" * %s: <%s> %sx%s (%s)", src.tagName(), src.attr("abs:src"), src.attr("width"), src.attr("height"), trim(src.attr("alt"), 20)); else print(" * %s: <%s>", src.tagName(), src.attr("abs:src")); } print("\nImports: (%d)", imports.size()); for (Element link : imports) { print(" * %s <%s> (%s)", link.tagName(), link.attr("abs:href"), link.attr("rel")); } print("\nLinks: (%d)", links.size()); for (Element link : links) { print(" * a: <%s> (%s)", link.attr("abs:href"), trim(link.text(), 35)); } } private static void print(String msg, Object... args) { System.out.println(String.format(msg, args)); } private static String trim(String s, int width) { if (s.length() > width) { return s.substring(0, width - 1) + "."; } else { return s; } }
情報を変更する
-
属性値を設定する
/** * @Author Liruilong * @Description * @Date 18:45 2020/3/24 * 在你解析一个Document之后可能想修改其中的某些属性值,然后再保存到磁盘或都输出到前台页面。 * 可以使用属性设置方法 Element.attr(String key, String value), 和 Elements.attr(String key, String value). * 假如你需要修改一个元素的 class 属性,可以使用 Element.addClass(String className) 和 Element.removeClass(String className) 方法。 * Elements 提供了批量操作元素属性和class的方法,比如:要为div中的每一个a元素都添加一个 rel="nofollow" 可以使用如下方法 * 与Element中的其它方法一样,attr 方法也是返回当 Element (或在使用选择器是返回 Elements 集合)。这样能够很方便使用方法连用的书写方式。 * **/ public static void test1(){ Document doc = Jsoup.parse(""); doc.select("div.comments a").attr("rel", "nofollow"); doc.select("div.masthead").attr("title", "jsoup").addClass("round-box"); }
-
要素のHTMLを設定します
/** * @Author Liruilong * @Description 设置一个元素的HTML内容 * @Date 18:56 2020/3/24 * Element.html(String html) 这个方法将先清除元素中的HTML内容,然后用传入的HTML代替。 * Element.prepend(String first) 和 Element.append(String last) 方法用于在分别在元素内部HTML的前面和后面添加HTML内容 * Element.wrap(String around) 对元素包裹一个外部HTML内容。 * Element.prependElement(String tag)和Element.appendElement(String tag) * 方法来创建新的元素并作为文档的子元素插入其中。 **/ public static void test2(){ Document doc = Jsoup.parse(""); Element div = doc.select("div").first(); // <div></div> div.html("<p>lorem ipsum</p>"); // <div><p>lorem ipsum</p></div> div.prepend("<p>First</p>");//在div前添加html内容 div.append("<p>Last</p>");//在div之后添加html内容 // 添完后的结果: <div><p>First</p><p>lorem ipsum</p><p>Last</p></div> Element span = doc.select("span").first(); // <span>One</span> span.wrap("<li><a href='http://example.com/'></a></li>"); // 添完后的结果: <li><a href="http://example.com"><span>One</span></a></li> }
Element.prependElement(String tag)
Element.appendElement(String tag) -
要素のテキストコンテンツを設定します
/** * @Author Liruilong * @Description 修改一个HTML文档中的文本内容 * @Date 19:06 2020/3/24 * Element.text(String text) 将清除一个元素中的内部HTML内容,然后提供的文本进行代替 * Element.prepend(String first) 和 Element.append(String last) 将分别在元素的内部html前后添加文本节点。 * 对于传入的文本如果含有像 <, > 等这样的字符,将以文本处理,而非HTML。 **/ public static void test3(){ Document doc = Jsoup.parse(""); Element div = doc.select("div").first(); // <div></div> div.text("five > four"); // <div>five > four</div> div.prepend("First "); div.append(" Last"); // now: <div>First five > four Last</div> }
Element.text(文字列テキスト)
HTMLをクリーンアップする
-
信頼できないHTMLをクリーンアップする(XSSを防ぐため)
/** * @Author Liruilong * @Description 消除不受信任的HTML (来防止XSS攻击) * @Date 19:16 2020/3/24 * 使用jsoup HTML Cleaner 方法进行清除,但需要指定一个可配置的 Whitelist。 * XSS又叫CSS (Cross Site Script) ,跨站脚本攻击。它指的是恶意攻击者往Web页面里插入恶意html代码, * 当用户浏览该页之时,嵌入其中Web里面的html代码会被执行, * 从而达到恶意攻击用户的特殊目的。XSS属于被动式的攻击,因为其被动且不好利用, * 所以许多人常忽略其危害性。所以我们经常只让用户输入纯文本的内容,但这样用户体验就比较差了。 * soup的whitelist清理器能够在服务器端对用户输入的HTML进行过滤,只输出一些安全的标签和属性。 * * jsoup提供了一系列的Whitelist基本配置,能够满足大多数要求;但如有必要,也可以进行修改,不过要小心。 * * 这个cleaner非常好用不仅可以避免XSS攻击,还可以限制用户可以输入的标签范围。 **/ public static void test4(){ String unsafe = "<p><a href='http://example.com/' onclick='stealCookies()'>Link</a></p>"; String safe = Jsoup.clean(unsafe, Whitelist.basic()); // now: <p><a href="http://example.com/" rel="nofollow">Link</a></p> }