日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

Jsoup学习总结

發(fā)布時(shí)間:2023/12/3 编程问答 27 豆豆
生活随笔 收集整理的這篇文章主要介紹了 Jsoup学习总结 小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

轉(zhuǎn)載自? ?Jsoup學(xué)習(xí)總結(jié)

摘要

Jsoup是一款比較好的Java版HTML解析器。可直接解析某個(gè)URL地址、HTML文本內(nèi)容。它提供了一套非常省力的API,可通過DOM,CSS以及類似于jQuery的操作方法來取出和操作數(shù)據(jù)。

jSOUP主要功能

  • 從一個(gè)URL,文件或字符串中解析HTML;
  • 使用DOM或CSS選擇器來查找、取出數(shù)據(jù);
  • 可操作HTML元素、屬性、文本;
  • 環(huán)境搭建

    MAVEN依賴

  • <dependency>
  • <groupId>org.jsoup</groupId>
  • <artifactId>jsoup</artifactId>
  • <version>1.8.3</version>
  • </dependency>
  • 1. 輸入

    jsoup 可以從包括字符串、URL地址以及本地文件來加載HTML 文檔,并生成Document對(duì)象實(shí)例。

    • Document對(duì)象(一個(gè)文檔的對(duì)象模型):文檔由多個(gè)Elements和TextNodes組成 (以及其它輔助nodes:詳細(xì)可查看:nodes package tree).?
      其繼承結(jié)構(gòu)如下:Document繼承Element繼承Node.?TextNode繼承?Node.

    • 一個(gè)Element包含一個(gè)子節(jié)點(diǎn)集合,并擁有一個(gè)父Element。他們還提供了一個(gè)唯一的子元素過濾列表。

    1.1 從字符串中輸入HTML文檔

    1.1.1 解析一個(gè)html字符串

    使用靜態(tài)方法Jsoup.parse(String html)?或?Jsoup.parse(String html, String baseUri)

  • String?html?=?"<html><head><title>開源中國(guó)社區(qū)</title></head>"
  • +"<body><p>這里是jsoup 項(xiàng)目的相關(guān)文章</p></body></html>";
  • Document?doc?=?Jsoup.parse(html);
  • 說明:

  • 其解析器能夠盡最大可能從你提供的HTML文檔來創(chuàng)見一個(gè)干凈的解析結(jié)果,無論HTML的格式是否完整。比如它可以處理:

    • 沒有關(guān)閉的標(biāo)簽 (比如:?<p>Lorem <p>Ipsum?解析為?<p>Lorem</p> <p>Ipsum</p>)
    • 隱式標(biāo)簽 (比如:它可以自動(dòng)將?<td>Table data</td>包裝成<table><tr><td>?)
    • 創(chuàng)建可靠的文檔結(jié)構(gòu)(html標(biāo)簽包含head 和 body,在head只出現(xiàn)恰當(dāng)?shù)脑?#xff09;
  • parse(String html, String baseUri)?這個(gè)方法能夠?qū)⑤斎氲腍TML解析為一個(gè)新的文檔 (Document),參數(shù) baseUri 是用來將相對(duì) URL 轉(zhuǎn)成絕對(duì)URL,并指定從哪個(gè)網(wǎng)站獲取文檔。如這個(gè)方法不適用,你可以使用?parse(String html)?方法來解析成HTML字符串如上面的示例。

  • 只要解析的不是空字符串,就能返回一個(gè)結(jié)構(gòu)合理的文檔,其中包含(至少) 一個(gè)head和一個(gè)body元素。

  • 一旦擁有了一個(gè)Document,你就可以使用Document中適當(dāng)?shù)姆椒ɑ蛩割?Element?和?Node?中的方法來取得相關(guān)數(shù)據(jù)

  • 1.1.2 解析一個(gè)body片斷

    假如你有一個(gè)HTML片斷 (比如. 一個(gè) div 包含一對(duì) p 標(biāo)簽; 一個(gè)不完整的HTML文檔) 想對(duì)它進(jìn)行解析。這個(gè)HTML片斷可以是用戶提交的一條評(píng)論或在一個(gè)CMS頁面中編輯body部分。可以使用Jsoup.parseBodyFragment(String html)?方法.

  • String?html?=?"<div><p>Lorem ipsum.</p>";
  • Document?doc?=?Jsoup.parseBodyFragment(html);
  • Element?body?=?doc.body();
  • 說明:

  • parseBodyFragment 方法創(chuàng)建一個(gè)空殼的文檔,并插入解析過的HTML到body元素中。假如你使用正常的?Jsoup.parse(String html)?方法,通常你也可以得到相同的結(jié)果,但是明確將用戶輸入作為 body片段處理,以確保用戶所提供的任何糟糕的HTML都將被解析成body元素。
  • Document.body()?方法能夠取得文檔body元素的所有子元素,與 doc.getElementsByTag("body")相同。
  • 1.2 從URL直接加載HTML文檔

    從一個(gè)網(wǎng)站獲取和解析一個(gè)HTML文檔,并查找其中的相關(guān)數(shù)據(jù),可以使用?Jsoup.connect(String url)方法。

  • Document?doc?=Jsoup.connect("網(wǎng)址/").get();
  • String?title?=?doc.title();
  • Document?doc?=Jsoup.connect("網(wǎng)址/")
  • .data("query",?"Java")?//請(qǐng)求參數(shù)
  • .userAgent("I’mjsoup")?//設(shè)置User-Agent
  • .cookie("auth",?"token")?//設(shè)置cookie
  • .timeout(3000)?//設(shè)置連接超時(shí)時(shí)間
  • .post();?//使用POST方法訪問URL
  • 說明:

  • connect(String url)?方法創(chuàng)建一個(gè)新的?Connection?和?get()?取得和解析一個(gè)HTML文件。如果從該URL獲取HTML時(shí)發(fā)生錯(cuò)誤,便會(huì)拋出 IOException,應(yīng)適當(dāng)處理。
  • Connection?接口還提供一個(gè)方法鏈來解決特殊請(qǐng)求,具體如下:
  • Document?doc?=?Jsoup.connect("http://example.com")
  • .data("query",?"Java")
  • .userAgent("Mozilla")
  • .cookie("auth",?"token")
  • .timeout(3000)
  • .post();
  • 這個(gè)方法只支持Web URLs (http 和 https 協(xié)議); 假如你需要從一個(gè)文件加載,可以使用?parse(File in, String charsetName)?代替。

    1.3 從文件中加載HTML文檔

    在本機(jī)硬盤上有一個(gè)HTML文件,需要對(duì)它進(jìn)行解析從中抽取數(shù)據(jù)或進(jìn)行修改。可以使用靜態(tài)?Jsoup.parse(File in, String charsetName, String baseUri)?方法。

  • File?input?=?new?File("/tmp/input.html");
  • Document?doc?=?Jsoup.parse(input,?"UTF-8",?"http://example.com/");
  • 說明:

  • parse(File in, String charsetName, String baseUri)?這個(gè)方法用來加載和解析一個(gè)HTML文件。如在加載文件的時(shí)候發(fā)生錯(cuò)誤,將拋出IOException,應(yīng)作適當(dāng)處理。

  • baseUri參數(shù)用于解決文件中URLs是相對(duì)路徑的問題。如果不需要可以傳入一個(gè)空的字符串。

  • 另外還有一個(gè)方法parse(File in, String charsetName)?它使用文件的路徑做為 baseUri。 這個(gè)方法適用于如果被解析文件位于網(wǎng)站的本地文件系統(tǒng),且相關(guān)鏈接也指向該文件系統(tǒng)。

  • 1.4 保證安全Stay safe

    假如你可以讓用戶輸入HTML內(nèi)容,那么要小心避免跨站腳本攻擊。利用基于Whitelist的清除器和clean(String bodyHtml, Whitelist whitelist)?方法來清除用戶輸入的惡意內(nèi)容。

    詳情查看 第4節(jié) [4.HTML清理](#4.HTML清理)

    2. 數(shù)據(jù)抽取

    2.1 使用DOM方法來遍歷一個(gè)文檔

    有一個(gè)HTML文檔要從中提取數(shù)據(jù),并了解這個(gè)HTML文檔的結(jié)構(gòu)。將HTML解析成一個(gè)Document之后,就可以使用類似于DOM的方法進(jìn)行操作。

  • File?input?=?new?File("/tmp/input.html");
  • Document?doc?=?Jsoup.parse(input,?"UTF-8",?"http://example.com/");
  • Element?content?=?doc.getElementById("content");
  • Elements?links?=?content.getElementsByTag("a");
  • for?(Element?link?:?links)?{
  • String?linkHref?=?link.attr("href");
  • String?linkText?=?link.text();
  • }
  • 說明:Elements這個(gè)對(duì)象提供了一系列類似于DOM的方法來查找元素,抽取并處理其中的數(shù)據(jù)。具體如下:

    2.1.1 查找元素

    getElementById(String id)id
    getElementsByTag(String tag)標(biāo)簽名
    getElementsByClass(String className)class名
    getElementsByAttribute(String key)屬性
    siblingElements()所有的兄弟元素
    firstElementSibling()第一個(gè)兄弟元素
    lastElementSibling()最后一個(gè)兄弟元素
    nextElementSibling()下一個(gè)兄弟元素
    previousElementSibling()上一個(gè)兄弟元素
    parent()獲取該元素父節(jié)點(diǎn)
    children()獲取該元素的子元素
    child(int index)獲取該元素的第幾個(gè)子元素(下標(biāo)從0開始)

    2.1.2 元素?cái)?shù)據(jù)

    attr(String key)獲取屬性
    attr(String key, String value)設(shè)置屬性
    attributes()獲取所有屬性
    id()獲取該元素id
    className()獲取該元素class,多個(gè)class之間空格隔開
    classNames()獲取所有元素的class
    text()獲取文本內(nèi)容
    text(String value)設(shè)置文本內(nèi)容
    html()獲取元素內(nèi)HTML
    html(String value)設(shè)置元素內(nèi)的HTML內(nèi)容
    outerHtml()獲取元素外HTML內(nèi)容
    data()獲取數(shù)據(jù)內(nèi)容(例如:script和style標(biāo)簽)
    tag()
    tagName()獲取元素標(biāo)簽名

    2.1.3 操作HTML和文本

    append(String html)添加給定的html到元素末尾
    prepend(String html)添加給定html到元素前面
    appendText(String text)創(chuàng)建并添加文本
    prependText(String text)創(chuàng)建并添加文本
    appendElement(String tagName)添加到元素末尾
    prependElement(String tagName)添加到元素前
    html(String value)設(shè)置元素值

    2.2 使用選擇器語法來查找元素(select)

    使用?Element.select(String selector)?和?Elements.select(String selector),使用類似于CSS或jQuery的語法來查找和操作元素。

  • File?input?=?new?File("/tmp/input.html");
  • Document?doc?=?Jsoup.parse(input,?"UTF-8",?"http://example.com/");
  • Elements?links?=?doc.select("a[href]");?//帶有href屬性的a元素
  • Elements?pngs?=?doc.select("img[src$=.png]");?//擴(kuò)展名為.png的圖片
  • Element?masthead?=?doc.select("div.masthead").first();//class等于masthead的div標(biāo)簽
  • Elements?resultLinks?=?doc.select("h3.r > a");?//在h3元素之后的a元素
  • 說明:?
    jsoup elements對(duì)象支持類似于CSS?(或jquery)的選擇器語法,來實(shí)現(xiàn)非常強(qiáng)大和靈活的查找功能。

    這個(gè)select?方法在Document,?Element,或Elements?對(duì)象中都可以使用。且是上下文相關(guān)的,因此可實(shí)現(xiàn)指定元素的過濾,或者鏈?zhǔn)竭x擇訪問。

    Select方法將返回一個(gè)Elements?集合,并提供一組方法來抽取和處理結(jié)果。

    2.2.1 Selector選擇器 基本用法

    tagname使用標(biāo)簽名來定位,例如 a
    ns|tag使用命名空間的標(biāo)簽定位,例如 fb:name 來查找?<fb:name>?元素
    #id使用元素 id 定位,例如 #logo
    .class使用元素的 class 屬性定位,例如 .head
    [attribute]使用元素的屬性進(jìn)行定位,例如 [href] 表示檢索具有 href 屬性的所有元素
    [^attr]使用元素的屬性名前綴進(jìn)行定位,例如 [^data-] 用來查找 HTML5 的 dataset 屬性
    [attr=value]使用屬性值進(jìn)行定位,例如 [width=500] 定位所有 width 屬性值為 500 的元素
    [attr^=value], [attr$=value], [attr*=value]利用匹配屬性值開頭、結(jié)尾或包含屬性值來查找元素,比如:[href*=/path/]
    [attr~=regex]利用屬性值匹配正則表達(dá)式來查找元素,例如img[src~=(?i).(png|jpe?g)]
    *定位所有元素

    2.2.2 Selector選擇器 組合使用

    el#id定位 id 值某個(gè)元素,例如 a#logo ->?<a id=logo href= … >
    el.class定位 class 為指定值的元素,例如 div.head ->?<div class="head">xxxx</div>
    el[attr]定位所有定義了某屬性的元素,例如 a[href]
    以上三個(gè)任意組合例如 a[href]#logo 、a[name].outerlink
    ancestor child查找某個(gè)元素下子元素,比如:可以用.body p?查找在"body"元素下的所有?p元素
    parent > child查找某個(gè)父元素下的直接子元素,比如:可以用div.content > p?查找?p?元素,也可以用body > *?查找body標(biāo)簽下所有直接子元素
    siblingA + siblingB查找在A元素之前第一個(gè)同級(jí)元素B,比如:div.head + div
    siblingA ~ siblingX查找A元素之前的同級(jí)X元素,比如:h1 ~ p
    el, el, el多個(gè)選擇器組合,查找匹配任一選擇器的唯一元素,例如:div.masthead, div.logo

    2.2.3 偽選擇器selectors (表達(dá)式):

    :lt(n)查找哪些元素的同級(jí)索引值(它的位置在DOM樹中是相對(duì)于它的父節(jié)點(diǎn))小于n,比如:td:lt(3)?表示小于三列的元素
    :gt(n)查找哪些元素的同級(jí)索引值大于n``,比如:?div p:gt(2)表示哪些div中有包含2個(gè)以上的p元素
    :eq(n)查找哪些元素的同級(jí)索引值與n相等,比如:form input:eq(1)表示包含一個(gè)input標(biāo)簽的Form元素
    :has(seletor)查找匹配選擇器包含元素的元素,比如:div:has(p)表示哪些div包含了p元素
    :not(selector)查找與選擇器不匹配的元素,比如:?div:not(.logo)?表示不包含 class="logo" 元素的所有 div 列表
    :contains(text)查找包含給定文本的元素,不區(qū)分大不寫,比如:?p:contains(jsoup)
    :containsOwn(text)查找文本信息完全等于指定條件的元素
    :matches(regex)使用正則表達(dá)式進(jìn)行文本過濾:div:matches((?i)login)
    :matchesOwn(regex)使用正則表達(dá)式找到自身的文本
    • 注意:上述偽選擇器索引是從0開始的,也就是說第一個(gè)元素索引值為0,第二個(gè)元素index為1等
    • 可以查看Selector?API參考來了解更詳細(xì)的內(nèi)容

    2.3 從元素抽取屬性,文本和HTML

    • Node.attr(String key)?獲取屬性值
    • Element.text()?獲取元素中的文本值
    • Element.html()?獲取元素HTML內(nèi)容
    • Node.outerHtml()?獲取元素HTML內(nèi)容
  • String?html?=?"<p>An <a href='http://example.com/'><b>example</b></a> link.</p>";
  • Document?doc?=?Jsoup.parse(html);//解析HTML字符串返回一個(gè)Document實(shí)現(xiàn)
  • Element?link?=?doc.select("a").first();//查找第一個(gè)a元素
  • String?text?=?doc.body().text();?// "An example link"//取得字符串中的文本
  • String?linkHref?=?link.attr("href");?// "http://example.com/"//取得鏈接地址
  • String?linkText?=?link.text();?// "example""//取得鏈接地址中的文本
  • String?linkOuterH?=?link.outerHtml();
  • // "<a href="http://example.com"><b>example</b></a>"
  • String?linkInnerH?=?link.html();?// "<b>example</b>"//取得鏈接內(nèi)的html內(nèi)容
  • 說明:?
    上述方法是元素?cái)?shù)據(jù)訪問的核心辦法。此外還其它一些方法可以使用:

    • Element.id()
    • Element.tagName()
    • Element.className()
    • Element.hasClass(String className)

    這些訪問器方法都有相應(yīng)的setter方法來更改數(shù)據(jù).

    2.4 處理URLs

    有一個(gè)包含相對(duì)URLs路徑的HTML文檔,需要將這些相對(duì)路徑轉(zhuǎn)換成絕對(duì)路徑的URLs。

  • 在解析文檔時(shí)確保有指定baseURI,
  • 然后使用?abs:?屬性前綴來取得包含baseURI的絕對(duì)路徑
  • Document?doc?=?Jsoup.connect("http://www.open-open.com").get();
  • Element?link?=?doc.select("a").first();
  • String?relHref?=?link.attr("href");?// == "/"
  • String?absHref?=?link.attr("abs:href");?// "http://www.open-open.com/"
  • 說明:?
    在HTML元素中,URLs經(jīng)常寫成相對(duì)于文檔位置的相對(duì)路徑:?<a href="/download">...</a>. 當(dāng)你使用?Node.attr(String key)?方法來取得a元素的href屬性時(shí),它將直接返回在HTML源碼中指定的值。

    假如你需要取得一個(gè)絕對(duì)路徑,需要在屬性名前加?abs:?前綴。這樣就可以返回包含根路徑的URL地址attr("abs:href"),因此,在解析HTML文檔時(shí),定義baseURI非常重要。

    如果你不想使用abs:?前綴,還有一個(gè)方法能夠?qū)崿F(xiàn)同樣的功能?Node.absUrl(String key)。

    2.5 示例程序: 獲取所有鏈接

    這個(gè)示例程序?qū)⒄故救绾螐囊粋€(gè)URL獲得一個(gè)頁面。然后提取頁面中的所有鏈接、圖片和其它輔助內(nèi)容。并檢查URLs和文本信息。運(yùn)行下面程序需要指定一個(gè)URLs作為參數(shù)

  • package?org.jsoup.examples;
  • import?org.jsoup.Jsoup;
  • import?org.jsoup.helper.Validate;
  • import?org.jsoup.nodes.Document;
  • import?org.jsoup.nodes.Element;
  • import?org.jsoup.select.Elements;
  • import?java.io.IOException;
  • /**
  • * Example program to list links from a URL.
  • */
  • public?class?ListLinks?{
  • public?static?void?main(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.tagName().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;
  • }
  • }
  • 示例輸入結(jié)果:

  • Fetching?http://news.ycombinator.com/...
  • Media:?(38)
  • *?img:?<http://ycombinator.com/images/y18.gif> 18x18 ()
  • *?img:?<http://ycombinator.com/images/s.gif> 10x1 ()
  • *?img:?<http://ycombinator.com/images/grayarrow.gif> x ()
  • *?img:?<http://ycombinator.com/images/s.gif> 0x10 ()
  • *?script:?<http://www.co2stats.com/propres.php?s=1138>
  • *?img:?<http://ycombinator.com/images/s.gif> 15x1 ()
  • *?img:?<http://ycombinator.com/images/hnsearch.png> x ()
  • *?img:?<http://ycombinator.com/images/s.gif> 25x1 ()
  • *?img:?<http://mixpanel.com/site_media/images/mixpanel_partner_logo_borderless.gif> x (Analytics by Mixpan.)
  • Imports:?(2)
  • *?link?<http://ycombinator.com/news.css> (stylesheet)
  • *?link?<http://ycombinator.com/favicon.ico> (shortcut icon)
  • Links:?(141)
  • *?a:?<http://ycombinator.com> ()
  • *?a:?<http://news.ycombinator.com/news> (Hacker News)
  • *?a:?<http://news.ycombinator.com/newest> (new)
  • *?a:?<http://news.ycombinator.com/newcomments> (comments)
  • *?a:?<http://news.ycombinator.com/leaders> (leaders)
  • *?a:?<http://news.ycombinator.com/jobs> (jobs)
  • *?a:?<http://news.ycombinator.com/submit> (submit)
  • *?a:?<http://news.ycombinator.com/x?fnid=JKhQjfU7gW> (login)
  • *?a:?<http://news.ycombinator.com/vote?for=1094578&dir=up&whence=%6e%65%77%73> ()
  • *?a:?<http://www.readwriteweb.com/archives/facebook_gets_faster_debuts_homegrown_php_compiler.php?utm_source=feedburner&utm_medium=feed&utm_campaign=Feed%3A+readwriteweb+%28ReadWriteWeb%29&utm_content=Twitter> (Facebook speeds up PHP)
  • *?a:?<http://news.ycombinator.com/user?id=mcxx> (mcxx)
  • *?a:?<http://news.ycombinator.com/item?id=1094578> (9 comments)
  • *?a:?<http://news.ycombinator.com/vote?for=1094649&dir=up&whence=%6e%65%77%73> ()
  • *?a:?<http://groups.google.com/group/django-developers/msg/a65fbbc8effcd914> ("Tough. Django produces XHTML.")
  • *?a:?<http://news.ycombinator.com/user?id=andybak> (andybak)
  • *?a:?<http://news.ycombinator.com/item?id=1094649> (3 comments)
  • *?a:?<http://news.ycombinator.com/vote?for=1093927&dir=up&whence=%6e%65%77%73> ()
  • *?a:?<http://news.ycombinator.com/x?fnid=p2sdPLE7Ce> (More)
  • *?a:?<http://news.ycombinator.com/lists> (Lists)
  • *?a:?<http://news.ycombinator.com/rss> (RSS)
  • *?a:?<http://ycombinator.com/bookmarklet.html> (Bookmarklet)
  • *?a:?<http://ycombinator.com/newsguidelines.html> (Guidelines)
  • *?a:?<http://ycombinator.com/newsfaq.html> (FAQ)
  • *?a:?<http://ycombinator.com/newsnews.html> (News News)
  • *?a:?<http://news.ycombinator.com/item?id=363> (Feature Requests)
  • *?a:?<http://ycombinator.com> (Y Combinator)
  • *?a:?<http://ycombinator.com/w2010.html> (Apply)
  • *?a:?<http://ycombinator.com/lib.html> (Library)
  • *?a:?<http://www.webmynd.com/html/hackernews.html> ()
  • *?a:?<http://mixpanel.com/?from=yc> ()
  • 3. 數(shù)據(jù)修改

    3.1 設(shè)置屬性的值

    在解析一個(gè)Document之后可能想修改其中的某些屬性值,然后再保存到磁盤或都輸出到前臺(tái)頁面。

    可以使用屬性設(shè)置方法?Element.attr(String key, String value), 和?Elements.attr(String key, String value).

    假如你需要修改一個(gè)元素的?class?屬性,可以使用?Element.addClass(String className)?和Element.removeClass(String className)?方法。

    Elements?提供了批量操作元素屬性和class的方法,比如:要為div中的每一個(gè)a元素都添加一個(gè)rel="nofollow"?可以使用如下方法:

  • doc.select("div.comments a").attr("rel",?"nofollow");
  • 說明:與Element?中的其它方法一樣,attr?方法也是返回當(dāng)前?Element?(或在使用選擇器是返回?Elements?集合)。這樣能夠很方便使用方法連用的書寫方式。比如:

  • doc.select("div.masthead").attr("title",?"jsoup").addClass("round-box");
  • 3.2 設(shè)置一個(gè)元素的HTML內(nèi)容

  • 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內(nèi)容
  • div.append("<p>Last</p>");//在div之后添加html內(nèi)容
  • // 添完后的結(jié)果: <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>");
  • // 添完后的結(jié)果: <li><a href="http://example.com"><span>One</span></a></li>
  • 說明:

    • Element.html(String html)?這個(gè)方法將先清除元素中的HTML內(nèi)容,然后用傳入的HTML代替。
    • Element.prepend(String first)?和?Element.append(String last)?方法用于在分別在元素內(nèi)部HTML的前面和后面添加HTML內(nèi)容
    • Element.wrap(String around)?對(duì)元素包裹一個(gè)外部HTML內(nèi)容。

    3.3 設(shè)置元素的文本內(nèi)容

  • Element?div?=?doc.select("div").first();?// <div></div>
  • div.text("five > four");?// <div>five &gt; four</div>
  • div.prepend("First ");
  • div.append(" Last");
  • // now: <div>First five &gt; four Last</div>
  • 說明:?
    文本設(shè)置方法與?HTML setter?方法一樣:

    • Element.text(String text)?將清除一個(gè)元素中的內(nèi)部HTML內(nèi)容,然后提供的文本進(jìn)行代替
    • Element.prepend(String first)?和?Element.append(String last)?將分別在元素的內(nèi)部html前后添加文本節(jié)點(diǎn)。

    對(duì)于傳入的文本如果含有像?<,?>?等這樣的字符,將以文本處理,而非HTML。

    4.HTML清理

    4.1 消除不受信任的HTML (防止XSS攻擊)

    在做網(wǎng)站的時(shí)候,經(jīng)常會(huì)提供用戶評(píng)論的功能。有些不懷好意的用戶,會(huì)搞一些腳本到評(píng)論內(nèi)容中,而這些腳本可能會(huì)破壞整個(gè)頁面的行為,更嚴(yán)重的是獲取一些機(jī)要信息,此時(shí)需要清理該HTML,以避免跨站腳本cross-site scripting攻擊(XSS)。?
    使用jsoup HTML?Cleaner?方法進(jìn)行清除,但需要指定一個(gè)可配置的?Whitelist。

  • 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>
  • 說明:?
    XSS又叫CSS (Cross Site Script) ,跨站腳本攻擊。它指的是惡意攻擊者往Web頁面里插入惡意html代碼,當(dāng)用戶瀏覽該頁之時(shí),嵌入其中Web里面的html代碼會(huì)被執(zhí)行,從而達(dá)到惡意攻擊用戶的特殊目的。XSS屬于被動(dòng)式的攻擊,因?yàn)槠浔粍?dòng)且不好利用,所以許多人常忽略其危害性。所以我們經(jīng)常只讓用戶輸入純文本的內(nèi)容,但這樣用戶體驗(yàn)就比較差了。

    一個(gè)更好的解決方法就是使用一個(gè)富文本編輯器WYSIWYG如CKEditor?和?TinyMCE。這些可以輸出HTML并能夠讓用戶可視化編輯。雖然他們可以在客戶端進(jìn)行校驗(yàn),但是這樣還不夠安全,需要在服務(wù)器端進(jìn)行校驗(yàn)并清除有害的HTML代碼,這樣才能確保輸入到你網(wǎng)站的HTML是安全的。否則,攻擊者能夠繞過客戶端的Javascript驗(yàn)證,并注入不安全的HMTL直接進(jìn)入您的網(wǎng)站。

    jsoup的whitelist清理器能夠在服務(wù)器端對(duì)用戶輸入的HTML進(jìn)行過濾,只輸出一些安全的標(biāo)簽和屬性。

    jsoup提供了一系列的Whitelist基本配置,能夠滿足大多數(shù)要求;但如有必要,也可以進(jìn)行修改,不過要小心。

    這個(gè)cleaner非常好用不僅可以避免XSS攻擊,還可以限制用戶可以輸入的標(biāo)簽范圍。

    jsoup 使用一個(gè) Whitelist 類用來對(duì) HTML 文檔進(jìn)行過濾,該類提供幾個(gè)常用方法:

    4.2 whitelist常用方法

    API查看:Whitelist

    方法名簡(jiǎn)介
    none()只允許包含文本信息
    basic()允許的標(biāo)簽包括:a, b, blockquote, br, cite, code, dd, dl, dt, em, i, li, ol, p, pre, q, small, strike, strong, sub, sup, u, ul, 以及合適的屬性
    simpleText()只允許 b, em, i, strong, u 這些標(biāo)簽
    basicWithImages()在 basic() 的基礎(chǔ)上增加了圖片
    relaxed()這個(gè)過濾器允許的標(biāo)簽最多,包括:a, b, blockquote, br, caption, cite, code, col, colgroup, dd, dl, dt, em, h1, h2, h3, h4, h5, h6, i, img, li, ol, p, pre, q, small, strike, strong, sub, sup, table, tbody, td, tfoot, th, thead, tr, u, ul

    如果這五個(gè)過濾器都無法滿足你的要求呢,例如你允許用戶插入 flash 動(dòng)畫,沒關(guān)系,Whitelist 提供擴(kuò)展功能,例如 whitelist.addTags("embed","object","param","span","div"); 也可調(diào)用 addAttributes 為某些元素增加屬性。

    參考:

    • 參閱XSS cheat sheet?,有一個(gè)例子可以了解為什么不能使用正則表達(dá)式,而采用安全的whitelist parser-based清理器才是正確的選擇。
    • 參閱Cleaner?,了解如何返回一個(gè)?Document?對(duì)象,而不是字符串
    • 參閱Whitelist,了解如何創(chuàng)建一個(gè)自定義的whitelist
    • nofollow?鏈接屬性了解

    5.更多參考

      • select用法詳解
      • jsoup 總結(jié)

    總結(jié)

    以上是生活随笔為你收集整理的Jsoup学习总结的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。