2012-07-27

Hello Jsoup 1.6.3

處理 HTML 的好工具。

讀 HTML 有兩種方式:

  • DOM Navigation - 幾乎是 DOM 與 jQuery 的 Java 版本,API 幾乎一樣
  • CSS Selector - 會 CSS 的就知道好用!

除了讀,還可以寫,API 幾乎是 jQuery 的翻版,還可以更正錯誤的 HTML 並輸出。

更棒的是,可以將相對路徑轉成絕對路徑!
/**
 * Jsoup 除了我知道的可以用 CSS Selector 來解析 HTML 外,還有一些神奇的功能
 * 例如修正錯誤的 HTML 格式後再輸出水水的 HTML、修改 HTML 內容
 */
public class HelloJsoup {

  /**
   * Jsoup.connect
   * 直接從網路抓 HTML 回來打
   * 支援 http 與 https
   */
  public void connect() throws IOException {
    Document doc = Jsoup.connect("http://en.wikipedia.org/").get();
    // Connection 有一堆設定可用
    // Connection c = Jsoup.connect("http://en.wikipedia.org/");
    // c.cookie("name", "value");
    // c.data("key", "value");
    // c.followRedirects(true);
    // c.header("name", "value");
    // c.timeout(5000);
    // c.userAgent("");
    // 也可以 post
    // Document doc = c.get();
    // Document doc = c.post();
    Elements es = doc.select("#mp-itn b a");
    System.out.println(es.size());
  }

  /**
   * Jsoup.parse
   * 解析本機的檔案
   */
  public void parseFile() throws IOException {
    Document d = Jsoup.parse(new File("/hello.html"), "UTF-8");
    System.out.println(d.html());
  }

  /**
   * Jsoup.parse or Jsoup.parseBodyFragment
   * 解析 HTML 字串
   * 修正錯誤的 HTML 語法,至少會有 html, head 與 body
   */
  public void correctBadHtml() {
    // 沒有任何 tag
    Document d = Jsoup.parse("Hello, Bad guy!");
    // d = Jsoup.parseBodyFragment("<table><td>Hello, Bad guy!</td>");
    System.out.println(d.html());
    // <html>
    // <head></head>
    // <body>
    // Hello, Bad guy!
    // </body>
    // </html>

    // 沒關門的 tag
    d = Jsoup.parse("<p>Hello, Bad guy!");
    // d = Jsoup.parseBodyFragment("<table><td>Hello, Bad guy!</td>");
    System.out.println(d.html());
    // <html>
    // <head></head>
    // <body>
    // <p>Hello, Bad guy!</p>
    // </body>
    // </html>

    // 不完整的 tag
    d = Jsoup.parse("<table><td>Hello, Bad guy!</td>");
    // d = Jsoup.parseBodyFragment("<table><td>Hello, Bad guy!</td>");
    System.out.println(d.html());
    // <html>
    // <head></head>
    // <body>
    // <table>
    // <tbody>
    // <tr>
    // <td>Hello, Bad guy!</td>
    // </tr>
    // </tbody>
    // </table>
    // </body>
    // </html>
  }

  /**
   * Jsoup.parse(html, baseUrl)
   * 在解析時傳入網址,使用 abs:href 或者 absUrl() 將相對路徑轉成絕對路徑
   */
  public void absoluteUrl() {
    // 第二個參數:http://www.neil.idv/,必須以 / 結尾
    Document d = Jsoup.parse(
        "<a href='http://neil.idv/absolute.do'>Absolute</a><a href='../relative.do'>Relative</a>",
        "http://www.neil.idv/abc/");
    Elements es = d.select("a");
    for (Element e : es) {
      System.out.println(e.text() + " href to " + e.attr("href"));
      System.out.println(e.text() + " abs:href to " + e.attr("abs:href"));
      System.out.println(e.text() + " absUrl to " + e.absUrl("href"));
    }
    // Absolute href to http://neil.idv/absolute.do
    // Absolute abs:href to http://neil.idv/absolute.do
    // Absolute absUrl to http://neil.idv/absolute.do
    // Relative href to ../relative.do
    // Relative abs:href to http://www.neil.idv/relative.do
    // Relative absUrl to http://www.neil.idv/relative.do
  }

  /**
   * DOM Navigation
   */
  public void domNavigate() throws IOException {
    Document d = Jsoup.connect("https://www.google.com/").get();
    Elements es = d.getElementsByTag("a");
    for (Element e : es) {
      System.out.println(e.text() + " links to " + e.attr("href"));
    }
  }

  /**
   * CSS Selector
   */
  public void cssSelector() throws IOException {
    Document d = Jsoup.connect("https://www.google.com/").get();
    System.out.println(d.html());
    Elements links = d.select("a[href]");
    for (Element e : links) {
      System.out.println(e.text() + " links to " + e.attr("href"));
    }
    Elements pngs = d.select("img[src$=.jpg]");
    for (Element e : pngs) {
      System.out.println(e.attr("src"));
    }
    // 除了 Document,還有 Element 與 Elements 都可以使用 select()
    Elements gbar = d.select("div#gbar");
    Elements gbarlinks = gbar.select("a");
    for (Element e : gbarlinks) {
      System.out.println(e.text() + " links to " + e.attr("href"));
    }
  }

  /**
   * 一堆快速的 method
   */
  public void document() throws IOException {
    Document doc = Jsoup.connect("https://www.google.com/").get();
    // 讀值
    System.out.println("title: " + doc.title());
    System.out.println("head: " + doc.head());
    System.out.println("body: " + doc.body());
    System.out.println("html: " + doc.html());
    System.out.println("outerHtml: " + doc.outerHtml());
    System.out.println("text: " + doc.text());
    System.out.println("attr: " + doc.attr("id"));
    System.out.println("id: " + doc.id());
    System.out.println("tagName: " + doc.tagName());
    System.out.println("className: " + doc.className());
    System.out.println("hasClass: " + doc.hasClass("clazz"));
    // 寫值
    doc.attr("key", "newValue");
    doc.addClass("clazz");
    doc.removeClass("clazz");
  }

  /**
   * 使用者輸入的 html 總是危險的
   */
  public String xss(String dangerousHtml) {
    return Jsoup.clean(dangerousHtml, Whitelist.basic());
  }
}

Document 與 Element 架構


DOM Navigation


CSS Selector


---

沒有留言:

張貼留言