Jsoup静态网页解析

Jsoup介绍

jsoup是一款Java的HTMIL解析器,可直接解析某个URL地址、HTML文本内容。它提供了一套非常省力的API,可通过DOM,CSS以及类似于jQuery的操作方法来取出和操作数据。.

jsoup的主要功能如下:

  1. 从一个URL,文件(HTML文件)或字符串中解析HTML;
  2. 使用DOM 或 CSS选择器来查找、取出数据;
  3. 可操作HTML元素、属性、文本;

####相应依赖

		<!-- jsoup-->
        <dependency>
            <groupId>org.jsoup</groupId>
            <artifactId>jsoup</artifactId>
            <version>1.10.2</version>
        </dependency>
		<!-- commons-io:用于操作文件-->
        <dependency>
            <groupId>commons-io</groupId>
            <artifactId>commons-io</artifactId>
            <version>2.6</version>
        </dependency>
		<!-- commons-lang3:使用StringUtils工具类 -->
        <dependency>
            <groupId>org.apache.commons</groupId>
            <artifactId>commons-lang3</artifactId>
            <version>3.7</version>
        </dependency>

使用

1. 解析url地址(使用比较少):

    public void testUrl() throws Exception{
        // 解析url地址,第一个参数是访问的url,第二个参数是访问的时候的超时时间
        Document doc= Jsoup.parse(new URL("http://www.itcast.cn"), 1000);

        // 使用标签选择器,获取title标签中的内容 .first():表示的为第一个element .text():表示获得文档中的内容
        String title = doc.getElementsByTag("title").first().text();

        // 打印测试
        System.out.println(title);
    }
为什么要使用httpclient发出http请求解析数据,而不是直接使用jsoup?

虽然使用Jsoup可以替代HttpClient直接发起请求解析数据,但是往往不会这样用,因为实际的开发过程中,需要使用到多线程,连接池,代理等等方式,而jsoup对这些的支持并不是很好,所以我们一般把jsoup 仅仅作为 Html解析工具使用。

2. 解析字符串(使用比较少):

    public void testString() throws Exception{
        // 使用工具类读取文件,获取字符串
        String content = FileUtils.readFileToString(new File("C:\\Users\\ZRE\\Desktop\\test.html"), "utf8");

        // 解析字符串
        Document document = Jsoup.parse(content);
        // 获得title的内容
        String title = document.getElementsByTag("title").first().text();

        System.out.println(title);
    }

3. 解析html文件(使用比较少):

    public void testFile() throws  Exception{
        // 解析文件
        Document doc = Jsoup.parse(new File("C:\\Users\\ZRE\\Desktop\\test.html"), "utf8");
        String title = doc.getElementsByTag("title").first().text();
        System.out.println(title);
    }

4. 使用dom方式遍历文档

元素获取:
  1. 根据id查询元素getElementByld
  2. 根据标签获取元素getElementsByTag
  3. 根据class获取元素getElementsByClass
  4. 根据属性获取元素getElementsByAttribute
 public void testDom() throws Exception{
        // 解析文件,获取Document对象
        Document document = Jsoup.parse(new File("C:\\Users\\ZRE\\Desktop\\test.html"), "utf8");

        //1. 根据id查询元素getElementByld
        //Element element = document.getElementById("city_bj");
        //2. 根据标签获取元素getElementsByTag
        //Element element = document.getElementsByTag("span").first();
        //3. 根据class获取元素getElementsByClass
        //Element element = document.getElementsByClass("class_a class_b").first();
        //4. 根据属性获取元素getElementsByAttribute
        //Element element = document.getElementsByAttribute("abc").first();
        //5. 通过属性+属性值获取元素
        Element element = document.getElementsByAttributeValue("href", "http://www.gz.itcast.cn").first();
        //打印元素的内容
        System.out.println("获取到的元素内容==>"+element.text());

    }
从元素中获取数据
  1. 从元素中获取id
  2. 从元素中获取className.
  3. 从元素中获取属性的值 attr
  4. 从元素中获取所有属性attributes
  5. 从元素中获取文本内容text
 // 解析文件,获得Document文档
        Document document = Jsoup.parse(new File("C:\\Users\\ZRE\\Desktop\\test.html"), "utf8");
        // 根据id获取元素
        Element element = document.getElementById("test");

        String str = null;
        //从元素中获取数据
        //1. 从元素中获取id
        str = element.id();

        //2. 从元素中获取className
        str = element.className();
//        Set<String> classSet = element.classNames();
//        for (String s : classSet) {
//            System.out.println(s);
//        }
        //3. 从元素中获取属性的值 attr
        str = element.attr("class");
        //4. 从元素中获取所有属性attributes
        Attributes attributes = element.attributes();

        System.out.println(attributes.toString());
        //5. 从元素中获取文本内容text
        str = element.text();
        //打印获取到的内容
        System.out.println("获取到的数据是=>"+str);
    }

5. 使用Selector选择器进行文档的解析

Selector选择器的简单使用
  1. tagname:通过标签查找元素, 比如: span
  2. #id:通过ID查找元素, 比如: #city_bj
  3. .class:通过class名称查找元素, 比如: .class_a
  4. [attribute]:利用属性查找元素, 比如:[abc]
  5. [attr=value]:利用属性值来查找元素, 比如: [class=s_name]
    public void testSelector() throws Exception{

        //解析html文件,获得document对象
        Document document = Jsoup.parse(new File("C:\\Users\\ZRE\\Desktop\\test.html"), "utf8");

        //1. tagname:通过标签查找元素,	比如: span
        Elements elements = document.select("span");
//        for (Element element : elements) {
//            System.out.println(element.text());
//        }
        //2. #id:通过ID查找元素,	比如: #city_bj
        //Element element = document.select("#city_bj").first();
        //3. .class:通过class名称查找元素,	比如: .class_a
        //Element element = document.select(".class_a").first();
        //4. [attribute]:利用属性查找元素,	比如:[abc]
        //Element element = document.select("[abc]").first();
        //5. [attr=value]:利用属性值来查找元素,	比如: [class=s_name]
        Elements elements1 = document.select("[class=s_name]");
        for (Element element : elements1) {
            System.out.println(element.text());
        }
        //打印结果
        //System.out.println("获取到的结果是=>"+element.text());
    }
Selector选择器组合使用
el#id:元素+ID:

比如:h3tcity_bj

el.class:元素+class:

比如:li.class_au

el[attr]:元素+属性名:

比如:span[abc]

任意组合:

比如: span[abc].s_name

ancestor child:查找某个元素下子元素:

比如: .city_con li查找"city_con"下的所有li

parent > child:查找某个父元素下的直接子元素:

比如:.city_con >ul>li查找city_con第一级(直接子元紊)的ul,再找所有ul下的第一级li

parent >*:查找某个父元素下所有直接子元素。
public void testSelector2() throws Exception{
        //解析html文件,获得document对象
        Document document = Jsoup.parse(new File("C:\\Users\\ZRE\\Desktop\\test.html"), "utf8");
        // el#id:元素+ID:
        // 比如:h3#city_bj
        //Element element = document.select("h3#city_bj").first();
        // el.class:元素+class:
        // 比如:li.class_a
        Element element = document.select("li.class_a").first();
        // el[attr]:元素+属性名:
        // 比如:span[abc]
        element = document.select("span[abc]").first();
        // 任意组合:
        // 比如: span[abc].s_name
        element = document.select("span[abc].s_name").first();
        // 父子关系查询
            // ancestor child:查找某个元素下子元素:
            // 比如: .city_con li查找class为"city_con"下的所有li
        Elements elements = document.select(".city_con li");
        for (Element element1 : elements) {
            System.out.println("遍历的结果=>" + element1.text());
        }
            //直接子元素
            // parent > child:查找某个父元素下的直接子元素:
            // 比如:.city_con >ul>li查找city_con第一级(直接子元紊)的ul,再找所有ul下的第一级li
        Elements directElements = document.select(".city_con > ul > li");
        for (Element directElement : directElements) {
            System.out.println("直接子元素遍历=> " + directElement.text());
        }
        // parent >*:查找某个父元素下所有直接子元素。
        Elements allElements = document.select(".city_con > ul > *");
        for (Element allElement : allElements) {
            System.out.println("父元素下的所有的子元素=>"+ allElement.text());
        }
        System.out.println("获取到的内容为=>"+element.text());
    }

HttpClientUtil工具类

import org.apache.http.client.config.RequestConfig;
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.impl.conn.PoolingHttpClientConnectionManager;
import org.apache.http.util.EntityUtils;
import org.springframework.stereotype.Component;

import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.util.UUID;

@Component
public class HttpUtils {


    /**
     * 创建连接池管理器(通过构造方法)
     */
    private PoolingHttpClientConnectionManager cm;

    public HttpUtils() {
        this.cm = new PoolingHttpClientConnectionManager();

        //指定连接池的连接数、
            //设置最大连接数
            this.cm.setMaxTotal(100);
            //设置每个主机的最大连接数
            this.cm.setDefaultMaxPerRoute(10);
    }

    /**
     * 根据请求地址下载页面数据
     * @param url
     * @return 页面数据
     */
    public String doGetHtml(String url){
        //获取httpClient对象
        CloseableHttpClient httpClient = HttpClients.custom().setConnectionManager(cm).build();
        //创建httpClient请求对象,设置url地址
        HttpGet httpGet = new HttpGet(url);

        //设置请求信息
        httpGet.setConfig(this.getConfig());


        CloseableHttpResponse response = null;

        try {
            //使用httpCLient发起请求,获取相应
            response = httpClient.execute(httpGet);


            //解析相应,返回结果
            if (response.getStatusLine().getStatusCode() == 200){
                //判断响应体Entity是否不为空,如果不为空,则可以使用EntityUtils
                if (response.getEntity() != null){
                    String content = EntityUtils.toString(response.getEntity(), "utf8");
                    //返回结果
                    return content;
                }
            }
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            // 关闭response
            if (response != null){
                try {
                    response.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
        //返回空串
        return "";
    }



    /***
     * 下载图片
     * @param url
     * @return 图片名称
     */
    public String doGetImage(String url){
        //获取httpClient对象
        CloseableHttpClient httpClient = HttpClients.custom().setConnectionManager(cm).build();
        //创建httpClient请求对象,设置url地址
        HttpGet httpGet = new HttpGet(url);

        //设置请求信息
        httpGet.setConfig(this.getConfig());


        CloseableHttpResponse response = null;

        try {
            //使用httpCLient发起请求,获取相应
            response = httpClient.execute(httpGet);


            //解析相应,返回结果
            if (response.getStatusLine().getStatusCode() == 200){
               if(response.getEntity() != null){
                   // 下载图片
                   // 获取图片后缀
                   String extName = url.substring(url.lastIndexOf("."));

                   // 创建图片名,重命名图片
                   String picName = UUID.randomUUID().toString()+extName;

                   // 下载图片
                   // 声明outputStream
                   OutputStream outputStream = new FileOutputStream(new File("C:\\Users\\ZRE\\Desktop\\images\\"+picName));
                   response.getEntity().writeTo(outputStream);
                   // 返回图片名称
                   return picName;
               }
            }
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            // 关闭response
            if (response != null){
                try {
                    response.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
        //如果下载失败,则返回空串
        return "";
    }

    /***
     * 设置请求信息
     * @return requestConfig
     */
    private RequestConfig getConfig() {
        RequestConfig requestConfig = RequestConfig.custom()
                .setConnectTimeout(1000)    //创建连接的最长时间
                .setConnectionRequestTimeout(500)   //获取连接的最长时间
                .setSocketTimeout(10*1000)  //数据传输的最长时间
                .build();
        return requestConfig;
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值