都知道爬虫用python,Java 爬虫你会吗?

在这篇文章中,将详细介绍 Jsoup 的相关知识,包括其功能与特点、基本用法、高级应用、原理分析、相关工具及框架等方面。

一、功能与特点

Jsoup 是一个用于解析 HTML 的 Java 库,提供了一组易于使用的 API 和方法,能够方便地从网页中提取出所需数据,以便于 Web 抓取和数据挖掘等领域的应用。其主要功能如下:

  1. 解析 HTML:Jsoup 可以将 HTML 文档解析成一个 DOM 树,便于后续操作。

  2. 查找元素:Jsoup 提供了多种查找元素的方法,包括根据标签名、属性名、类名、ID 等查找方式。

  3. 获取元素信息:Jsoup 可以获取元素的属性和文本内容。

  4. 操作 DOM 树:Jsoup 可以对 DOM 树进行添加、删除、修改节点等操作。

  5. 支持 CSS 选择器:Jsoup 可以使用 CSS 选择器语法查找元素。

  6. 支持链式调用:Jsoup 的 API 设计简单易用,支持链式调用,代码清晰简洁。

  7. 支持 UTF-8 编码:Jsoup 默认采用 UTF-8 编码处理文本,能够处理中文等特殊字符。

二、基本用法

  1. 导入 Jsoup

在 Java 代码中使用 Jsoup 需要先导入 Jsoup 相关的依赖库,可以通过 Maven 或手动安装两种方式来实现。例如使用 Maven 导入 Jsoup:

<dependency>
    <groupId>org.jsoup</groupId>
    <artifactId>jsoup</artifactId>
    <version>x.x.x</version>
</dependency>

其中 x.x.x 表示需要使用的 Jsoup 版本号。

  1. 连接 URL

Jsoup.connect(String url) 方法用于连接指定 URL,并返回一个 Connection 对象,其后可以链式调用其他参数设置方法进行个性化定制。例如:

Connection conn = Jsoup.connect("http://example.com/")
                     .userAgent("Mozilla")
                     .timeout(5000)
                     .referrer("http://google.com")
                     .header("Accept-Language", "en-US");

常用参数设置方法如下:

  • userAgent(String userAgent):设置用户代理
  • timeout(int milliseconds):设置连接超时时间
  • ignoreHttpErrors(boolean ignore):是否忽略 HTTP 错误(404、500 等)
  • ignoreContentType(boolean ignore):是否忽略内容类型
  • referrer(String referrer):设置 Referrer
  • headers(Map<String, String> headers):设置请求头
  1. 获取HTML内容

Connection.get() 方法用于获取与此连接对应的 HTML 文档,并返回一个 Document 对象。例如:

Document doc = Jsoup.connect("http://example.com/").get();

如果需要使用 POST 请求,则可以使用 Connection.post() 方法:

Document doc = Jsoup.connect("http://example.com/login")
                     .data("username", "admin")
                     .data("password", "123456")
                     .post();

需要注意的是,如果提交表单时需要使用 enctype=”multipart/form-data” 类型,则不能使用 Connection.data() 方法。

  1. 解析HTML内容

Jsoup 提供了许多方法和工具来解析 HTML 内容,例如根据标签名/属性名/类名查找元素、遍历 DOM 树、获取元素的属性和文本内容等。

  • 解析 HTML 字符串:parse(String html) 方法可用于解析一个 HTML 字符串,并将其转换为 Document 对象。例如:

    String html = "<html><head><title>Jsoup Example</title></head><body><p>Hello World!</p></body></html>";
    Document doc = Jsoup.parse(html);
    
  • 查找元素:

    • Document.select(String cssQuery) 方法可以根据 CSS 选择器选取元素,返回一个 Elements 对象。例如:

      Elements links = doc.select("a[href]");
      
    • Element.getElementsByTag(String tag) 方法可用于根据标签名选取元素,返回一个 Elements 对象。例如:

      Elements paragraphs = doc.getElementsByTag("p");
      
    • Element.getElementsByAttribute(String key) 方法可用于根据属性名选取元素,返回一个 Elements 对象。例如:

      Elements links = doc.getElementsByAttribute("href");
      
    • Element.getElementsByAttributeValue(String key, String value) 方法可用于根据属性名和属性值选取元素,返回一个 Elements 对象。例如:

      Elements links = doc.getElementsByAttributeValue("rel", "nofollow");
      
    • Element.getElementsByClass(String className) 方法可用于根据类名选取元素,返回一个 Elements 对象。例如:

      Elements images = doc.getElementsByClass("image");
      
  • 获取元素信息:

    • Element.attr(String attributeKey) 方法可用于获取元素的属性值。例如:

      String href = link.attr("href");
      
    • Element.text() 方法可用于获取元素的文本内容。例如:

      String text = paragraph.text();
      
  • 迭代元素:

    • Elements.eachText() 方法将返回所有元素的文本内容,以字符串形式返回。例如:

      String allText = doc.select("body").eachText().toString();
      
    • Elements.iterator() 方法返回一个迭代器,用于遍历元素集合。例如:

      Iterator<Element> iter = doc.select("a[href]").iterator();
      while (iter.hasNext()) {
          Element link = iter.next();
          String href = link.attr("href");
          System.out.println(href);
      }
      
  1. 操作DOM树

Jsoup 提供了许多方法和工具来操作 DOM 树,例如添加、删除、修改节点等操作。

  • 添加节点:

    • Element.append(String html) 方法可用于向元素的末尾添加子元素。例如:

      Element div = doc.select("div").first();
      div.append("<p>Hello Jsoup</p>");
      
    • Element.prepend(String html) 方法可用于向元素的开头添加子元素。例如:

      Element div = doc.select("div").first();
      div.prepend("<p>Hello Jsoup</p>");
      
    • Element.html(String html) 方法可用于替换元素内部的 HTML 内容。例如:

      Element div = doc.select("div").first();
      div.html("<p>Hello Jsoup</p>");
      
    • Element.text(String text) 方法可用于替换元素内部的文本内容。例如:

      Element div = doc.select("div").first();
      div.text("Hello Jsoup");
      
  • 删除节点:

    • Element.empty() 方法可用于删除元素内部的所有子元素。例如:

      Element div = doc.select("div").first();
      div.empty();
      
    • Element.remove() 方法可用于删除元素本身。例如:

      Element div = doc.select("div").first();
      div.remove();
      
  • 修改节点:

    • Element.attr(String attributeKey, String attributeValue) 方法可用于修改元素的属性值。例如:

      Element link = doc.select("a[href]").first();
      link.attr("href", "http://example.com");
      
    • Element.addClass(String className) 方法可用于向元素添加类名。例如:

      Element div = doc.select("div").first();
      div.addClass("highlight");
      
    • Element.removeClass(String className) 方法可用于删除元素的类名。例如:

      Element div = doc.select("div").first();
      div.removeClass("highlight");
      

三、高级应用

  1. 处理错误和异常

在解析 HTML 时,有可能会出现各种错误和异常,例如网络超时、HTTP 错误、HTML 解析错误等。为了保证程序的健壮性和稳定性,需要对这些错误进行处理。

可以使用 try-catch 块来捕获异常,并采取相应的措施进行处理。例如:

try {
    Document doc = Jsoup.connect("http://example.com/").get();
} catch (IOException e) {
    System.err.println("IO Exception: " + e.getMessage());
} catch (IllegalArgumentException e) {
    System.err.println("Illegal Argument Exception: " + e.getMessage());
}
  1. 使用代理服务器

在实际应用中,有时需要使用代理服务器来访问互联网,以便实现一些特殊需求,例如爬虫、数据挖掘等。可以使用 Proxy 类来设置代理服务器。

String proxyHost = "proxy.example.com";
int proxyPort = 8080;
Proxy proxy = new Proxy(Proxy.Type.HTTP, new InetSocketAddress(proxyHost, proxyPort));
Document doc = Jsoup.connect("http://example.com/").proxy(proxy).get();
  1. 加载本地 HTML 文件

除了从 URL 加载 HTML 文档外,还可以从本地文件系统加载 HTML 文件,以便进行离线处理。可以使用 File 类来指定本地文件路径,并使用 Jsoup.parse(File in, String charsetName) 方法来解析文件。

File input = new File("input.html");
Document doc = Jsoup.parse(input, "UTF-8");
  1. 处理 AJAX 网页

在一些新型的网站中,由于采用了 AJAX 技术,页面内容可能会动态生成,而不是直接从服务器端加载。这时候,需要使用一些高级技巧来处理 AJAX 网页,例如 PhantomJS、Selenium 等技术。

四、原理分析

Jsoup 的内部实现原理比较复杂,主要涉及到 HTML 解析器、DOM 树构建器、字符编码处理器等组件。其中,HTML 解析器是核心组件之一,实现了对 HTML 语法的解析和分词,将 HTML 文档转换成一个 DOM 树。

具体而言,HTML 解析器采用了一种基于状态转移的解析算法,即根据当前状态和输入字符,确定下一步的状态和动作,并将解析过程记录在一个状态栈中。当解析完成后,栈中保存的状态信息即为最终的 DOM 树结构。

DOM 树构建器则负责将解析完成的状态栈转换成一个 DOM 树对象,以方便后续操作。字符编码处理器则负责将 HTML 文档中的特殊字符(例如中文、符号等)进行编码和解码,以保证在解析过程中不会出现乱码或错误。

五、相关工具及框架

除了 Jsoup 之外,还有许多其他的 HTML 解析工具和框架可供选择,具体如下:

  • Jsoup:一款轻量级的 Java HTML 解析器
  • NekoHTML:一款基于 Xerces 的轻量级 HTML 解析器,支持 SAX 和 DOM 模式
  • HTML Parser:一款基于 Java 的 HTML 解析器,支持 SAX 和 DOM 模式
  • Jericho HTML Parser:一款开源的 HTML 解析器,可以解析标准 HTML、XHTML、XML 等格式
  • TagSoup:一款开源的 HTML/XML 解析器,可以处理 HTML5、XML 等格式
  • Selenium:一款自动化测试工具,可以模拟浏览器行为,支持处理 AJAX 和 JavaScript 网页
  • PhantomJS:一种无界面的 WebKit 浏览器,支持处理 AJAX 和 JavaScript 网页,可以嵌入到 Java 程序中进行使用
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 206,378评论 6 481
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 88,356评论 2 382
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 152,702评论 0 342
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 55,259评论 1 279
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 64,263评论 5 371
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,036评论 1 285
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,349评论 3 400
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,979评论 0 259
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 43,469评论 1 300
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,938评论 2 323
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,059评论 1 333
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,703评论 4 323
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,257评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,262评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,485评论 1 262
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,501评论 2 354
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,792评论 2 345

推荐阅读更多精彩内容