Java爬虫入门简介(二) —— Jsoup解析HTML页面

Java爬虫入门简介(二) —— Jsoup解析HTML页面 原文链接:http://blog.csdn.net/df19900725/article/details/77587318

上一节我们获取了 http://www.datalearner.com/blog_list 页面的HTML源码,但是这些源码是提供给浏览器解析用的,我们需要的数据其实是页面上博客的标题、作者、简介、发布日期等。我们需要通过一种方式来从HTML源码中解析出这类信息并提取,然后存到文本或者数据库之中。在这篇博客中,我们将介绍使用Jsoup包帮助我们解析页面,提取数据。
Jsoup是一款Java的HTML解析器,可以直接解析某个URL地址,也可以解析HTML内容。其主要的功能包括解析HTML页面,通过DOM或者CSS选择器来查找、提取数据,可以更改HTML内容。Jsoup的使用方式也很简单,使用Jsoup.parse(String str)方法将之前我们获取到的HTML内容进行解析得到一个Documend类,剩下的工作就是从Document中选择我们需要的数据了。举个例子,假设我们有个HTML页面的内容如下:

<html>
<div id="blog_list">
    <div class="blog_title">
        <a href="url1">第一篇博客</a>
    </div>
    <div class="blog_title">
        <a href="url2">第二篇博客</a>
    </div>
    <div class="blog_title">
        <a href="url3">第三篇博客</a>
    </div>
</div>
</html>

通过Jsoup我们可以把上面的三篇博客的标题提取到一个List中。使用方法如下:

首先,我们通过maven把Jsoup引入进来

<!-- https://mvnrepository.com/artifact/org.jsoup/jsoup -->
<dependency>
<groupId>org.jsoup</groupId>
<artifactId>jsoup</artifactId>
<version>1.10.3</version>
</dependency>

然后编写Java进行解析。

package org.hfutec.example;

import org.jsoup.Jsoup;
import org.jsoup.nodes.Document;
import org.jsoup.nodes.Element;
import org.jsoup.select.Elements;

import java.util.ArrayList;
import java.util.List;

/*******
 * created by DuFei at 2017.08.25 21:00
 * web crawler example
 * ******/

public class DataLearnerCrawler {

  public static void main(String[] args) {

    List<String> titles = new ArrayList<String>();
    List<String> urls = new ArrayList<String>();

    //假设我们获取的HTML的字符内容如下
    String html = "<html><div id=\"blog_list\"><div class=\"blog_title\"><a href=\"url1\">第一篇博客</a></div><div class=\"blog_title\"><a href=\"url2\">第二篇博客</a></div><div class=\"blog_title\"><a href=\"url3\">第三篇博客</a></div></div></html>";

    //第一步,将字符内容解析成一个Document类
    Document doc = Jsoup.parse(html);

    //第二步,根据我们需要得到的标签,选择提取相应标签的内容
    Elements elements = doc.select("div[id=blog_list]").select("div[class=blog_title]");
    for( Element element : elements ){
      String title = element.text();
      titles.add(title);
      urls.add(element.select("a").attr("href"));
    }

    //输出测试
    for( String title : titles ){
      System.out.println(title);
    }

    for( String url : urls ){
      System.out.println(url);
    }

  }
}

我们简单说明一下Jsoup的解析过程。首先第一步都是调用parse()方法将字符对象变成一个Document对象,然后我们对这个对象进行操作。一般提取数据就是根据标签选择数据,使用select()方法语法格式和 JavaScript/css 选择器都是一样的。一般都是提取某个标签,其属性值为指定内容。得到的结果是一个Element的集合,为Elements(因为符合条件的标签可能很多,所以结果是一个集合)。select()方法可以一直进行下去,直到选择到我们想要的标签集合为止(注意,我们并不一定要按照标签层级一级一级往下选,可以直接写select()方法到我们需要的标签的上一级,比如这里的示例代码可以直接写成 Elements elements = doc.select(“div[class=blog_title]”); 其效果是一样的)。对于选择到的Elements的集合,我们可以通过循环的方式提取每一个需要的数据,比如,我们需要拿到标签的文本信息,就可以使用text()方法,如果我们需要拿到对应的HTML属性信息,我们可以使用attr()方法。我们可以看到上述方法的输出结果如下:

e39b4f52-98fc-4ed5-9c43-15b1dc04f823.jpg

更多的Jsoup解析的操作可以参考如下: 1、https://www.ibm.com/developerworks/cn/java/j-lo-jsouphtml/index.html 2、https://jsoup.org/
一个实例
我们接着上一个爬取数据学习官方网站博客列表的例子讲解一个实例。我们已经知道可以使用Jsoup来解析爬取到的HTML页面内容。那么如何查看我们需要的内容对应的标签呢?以Chrome浏览器为例,我们需要爬取http://www.datalearner.com/blog_list 这个页面的的博客,首先用Chrome浏览器打开这个网址,然后鼠标右键单击博客的标题,点击“检查”就可以得到HTML页面了。如下图所示。

94f6bf06-312a-4781-97c8-99d2b9d57884.jpg
d810463f-c23d-4dae-98cc-08764fbbef85.jpg
d310a4ae-c2e0-45f1-8637-9f8b390baa3b.jpg

图4 确认当前博客的HTML代码的一致性

通过上述操作之后,我们已经可以看到,所有的博客的标题等信息都存在class=card的div里面了。于是,我们只要关注这个标签里面的内容是如何组织的,就可以了。如下图所示,我们需要的信息所属的标签,通过点击小三角展开就能得到了。

7e161a6f-bbff-44e3-a422-08d18102cbb3.jpg

因此,解析博客列表的代码可以写成如下形式了。

package org.hfutec.example;

import org.apache.http.HttpEntity;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.util.EntityUtils;
import org.jsoup.Jsoup;
import org.jsoup.nodes.Document;
import org.jsoup.nodes.Element;
import org.jsoup.select.Elements;

import java.io.IOException;

/*******
 * created by DuFei at 2017.08.25 21:00
 * web crawler example
 * ******/

public class DataLearnerCrawler {

  public static void main(String[] args) {

String url = "http://www.datalearner.com/blog_list";
String rawHTML = null;
try {
  rawHTML = getHTMLContent(url);
} catch (IOException e) {
  e.printStackTrace();
}

//将当前页面转换成Jsoup的Document对象
Document doc = Jsoup.parse(rawHTML);

//获取所有的博客列表集合
Elements blogList = doc.select("div[class=card]");

//针对每个博客内容进行解析,并输出
for( Element element : blogList ){

  String title = element.select("h4[class=card-title]").text();
  String introduction = element.select("p[class=card-text]").text();
  String author = element.select("span[class=fa fa-user]").text();

  System.out.println("Title:\t"+title);
  System.out.println("introduction:\t"+introduction);
  System.out.println("Author:\t"+author);
  System.out.println("--------------------------");

}

  }

  //根据url地址获取对应页面的HTML内容,我们将上一节中的内容打包成了一个方法,方便调用
  private static String getHTMLContent( String url ) throws IOException {

//建立一个新的请求客户端
CloseableHttpClient httpClient = HttpClients.createDefault();

//使用HttpGet方式请求网址
HttpGet httpGet = new HttpGet(url);

//获取网址的返回结果
CloseableHttpResponse response = httpClient.execute(httpGet);

//获取返回结果中的实体
HttpEntity entity = response.getEntity();

String content = EntityUtils.toString(entity);

//关闭HttpEntity流
EntityUtils.consume(entity);

return content;

  }

}
e248e590-b1c7-4df3-b9ab-074fb86095ec.jpg
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 200,392评论 5 470
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 84,258评论 2 377
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 147,417评论 0 332
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 53,992评论 1 272
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 62,930评论 5 360
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,199评论 1 277
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,652评论 3 390
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,327评论 0 254
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,463评论 1 294
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,382评论 2 317
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,432评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,118评论 3 315
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,704评论 3 303
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,787评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 30,999评论 1 255
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,476评论 2 346
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,057评论 2 341

推荐阅读更多精彩内容

  • Android 自定义View的各种姿势1 Activity的显示之ViewRootImpl详解 Activity...
    passiontim阅读 171,280评论 25 707
  • Spring Cloud为开发人员提供了快速构建分布式系统中一些常见模式的工具(例如配置管理,服务发现,断路器,智...
    卡卡罗2017阅读 134,566评论 18 139
  • 在处理网页形式的文本时, 刚开始使用了scala.xml来解析 这样对完整格式的xml文本处理的很好,但是有些xm...
    点点渔火阅读 2,326评论 1 3
  • 看到今天的话题是:你最厉害的技能是什么?(工作,生活都可以),但仔细想想,能谈得上“技能”的东西实在是寥寥无几,更...
    萤风白阅读 215评论 0 0
  • Being alive is a gift.生活中想要的太多,一个又一个的目标,一场又一场竞赛,人们在生活中疲惫,...
    北窗一枕阅读 470评论 0 1