Java 爬虫工具Jsoup解析

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

jsoup 的主要功能如下:

1. 从一个 URL,文件或字符串中解析 HTML;

2. 使用 DOM 或 CSS 选择器来查找、取出数据;

3. 可操作 HTML 元素、属性、文本;

jsoup 是基于 MIT 协议发布的,可放心使用于商业项目。

jsoup 可以从包括字符串、URL 地址以及本地文件来加载 HTML 文档,并生成 Document 对象实例。

简单而言,Jsoup就是先取html页面代码然后解析这些页面通过Jsoup携带的满足我们绝大多数需求的各种选择器从这个页面中获取我们所需要的重要数据的一款功能强大的html解析器,但也只是相对而言,这里的页面这是死的静态页面,如果你想获取动态生成的页面数据那么你得用到其他的java 爬虫技术,我会不定时更新这些技术一起探讨。下面我们来具体谈谈如何运用Jsoup

一、如何取页面

Jsoup提供了用来解析html页面的方法 parse(),我们通过解析它可以获取整个页面的dom对象,通过这个对象来获取你所需要的页面所须有的参数。获取页面的方法有很多,这里就简单的列举几个:

① 通过Jsoup携带的connect()方法

String htmlPage = Jsoup.connect("https://www.baidu.com").get().toString();

这个方法说需要的参数就是一个String类型的url链接,但是你的注意把这些链接的protrol加上,以免问题,

其实这个方法解决了我们很多问题,我们完全可以把Jsoup解析html抽取成一段通用工具类,然后通过改变拼接的url参数获取到很多我们想要的东西,举个例子:京东和淘宝的商品链接都是固定的,通过改变其三方商品ID来获取商品详情参数。

String url = "https://item.jd.com/11476104681.html";

完全可以替换成

String url = "https://item.jd.com/"+skuId+".html";

通过改变他的三方商品ID你就可以获取这个页面一些基本数据,像商品的图片和标题什么的都可以轻松获取,而价格因为做了一些相关方面的处理得动态的获取,这里先不做说明,后面慢慢会讲解。

②通过httpclient直接获取这个页面的静态页面

先贴一部分httpclient获取页面工具



import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Set;

import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.NameValuePair;
import org.apache.http.ParseException;
import org.apache.http.client.ClientProtocolException;
import org.apache.http.client.entity.UrlEncodedFormEntity;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.client.methods.HttpUriRequest;
import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.http.message.BasicNameValuePair;
import org.apache.http.protocol.HTTP;
import org.apache.http.util.EntityUtils;
/**
 * HTTP请求工具类.
 * @author LuoLong
 * @since 20150513
 *
 */
public class HttpClientUtils {
    /**
     * post方式请求.
     * @param url 请求地址.
     * @param params 请求参数
     * @return String
     */
    public static String post(String url, Map<String, String> params) {
        DefaultHttpClient httpclient = new DefaultHttpClient();
        String body = null;

        HttpPost post = postForm(url, params);

        body = invoke(httpclient, post);

        httpclient.getConnectionManager().shutdown();

        return body;
    }

    /**
     * get方式请求.
     * @param url 请求地址.
     * @return String
     */
    public static String get(String url) {
        DefaultHttpClient httpclient = new DefaultHttpClient();
        String body = null;

        HttpGet get = new HttpGet(url);
        body = invoke(httpclient, get);

        httpclient.getConnectionManager().shutdown();

        return body;
    }
    /**
     * 请求方法.
     * @param httpclient DefaultHttpClient.
     * @param httpost 请求方式.
     * @return String
     */
    private static String invoke(DefaultHttpClient httpclient,
            HttpUriRequest httpost) {

        HttpResponse response = sendRequest(httpclient, httpost);
        String body = paseResponse(response);

        return body;
    }

    /**
     *
     * @param response
     * @return
     */
    @SuppressWarnings({ "deprecation", "unused" })
    private static String paseResponse(HttpResponse response) {
        HttpEntity entity = response.getEntity();

        String charset = EntityUtils.getContentCharSet(entity);

        String body = null;
        try {
            body = EntityUtils.toString(entity);
        } catch (ParseException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }

        return body;
    }

    private static HttpResponse sendRequest(DefaultHttpClient httpclient,
            HttpUriRequest httpost) {
        HttpResponse response = null;

        try {
            response = httpclient.execute(httpost);
        } catch (ClientProtocolException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
        return response;
    }

    @SuppressWarnings("deprecation")
    private static HttpPost postForm(String url, Map<String, String> params) {

        HttpPost httpost = new HttpPost(url);
        List<NameValuePair> nvps = new ArrayList<NameValuePair>();

        Set<String> keySet = params.keySet();
        for (String key : keySet) {
            nvps.add(new BasicNameValuePair(key, params.get(key)));
        }
        try {
            httpost.setEntity(new UrlEncodedFormEntity(nvps, HTTP.UTF_8));
        } catch (UnsupportedEncodingException e) {
            e.printStackTrace();
        }

        return httpost;
    }
}

通过get()方法就可以获取html页面的String类型数据

String content = HttpClientUtils.get(url);
或者你可以直接把页面下载到本地,然后解析此html文档获取
File input = new File(FilePath);
Document doc = Jsoup.parse(input, "UTF-8", url);

二、解析页面获取需要的数据

当你获取到页面的dom对象后,那么下面的操作就非常简单了,你只需要通过操作这个dom对象来获取页面所有的静态资源,动态加载的资源不在此列,后面在做讲解。

先贴一段百度网页的源代码:

  </form>
       <div id="m"></div>
      </div>
     </div>
     <div id="u">
      <a class="toindex" href="/">百度首页</a>
      <a href="javascript:;" name="tj_settingicon" class="pf">设置<i class="c-icon c-icon-triangle-down"></i></a>
      <a href="https://passport.baidu.com/v2/?login&amp;tpl=mn&amp;u=http%3A%2F%2Fwww.baidu.com%2F" name="tj_login" class="lb" onclick="return false;">登录</a>
     </div>
     <div id="u1">
      <a href="http://news.baidu.com" name="tj_trnews" class="mnav">新闻</a>
      <a href="http://www.hao123.com" name="tj_trhao123" class="mnav">hao123</a>
      <a href="http://map.baidu.com" name="tj_trmap" class="mnav">地图</a>
      <a href="http://v.baidu.com" name="tj_trvideo" class="mnav">视频</a>
      <a href="http://tieba.baidu.com" name="tj_trtieba" class="mnav">贴吧</a>
      <a href="http://xueshu.baidu.com" name="tj_trxueshu" class="mnav">学术</a>
      <a href="https://passport.baidu.com/v2/?login&amp;tpl=mn&amp;u=http%3A%2F%2Fwww.baidu.com%2F" name="tj_login" class="lb" onclick="return false;">登录</a>
      <a href="http://www.baidu.com/gaoji/preferences.html" name="tj_settingicon" class="pf">设置</a>
      <a href="http://www.baidu.com/more/" name="tj_briicon" class="bri" style="display: block;">更多产品</a>
     </div>
    </div>
   </div>
   <div class="s_tab" id="s_tab">
    <b>网页</b>
    <a href="http://news.baidu.com/ns?cl=2&amp;rn=20&amp;tn=news&amp;word=" wdfield="word" onmousedown="return c({‘fm‘:‘tab‘,‘tab‘:‘news‘})">新闻</a>
    <a href="http://tieba.baidu.com/f?kw=&amp;fr=wwwt" wdfield="kw" onmousedown="return c({‘fm‘:‘tab‘,‘tab‘:‘tieba‘})">贴吧</a>
    <a href="http://zhidao.baidu.com/q?ct=17&amp;pn=0&amp;tn=ikaslist&amp;rn=10&amp;word=&amp;fr=wwwt" wdfield="word" onmousedown="return c({‘fm‘:‘tab‘,‘tab‘:‘zhidao‘})">知道</a>
    <a href="http://music.baidu.com/search?fr=ps&amp;ie=utf-8&amp;key=" wdfield="key" onmousedown="return c({‘fm‘:‘tab‘,‘tab‘:‘music‘})">音乐</a>
    <a href="http://image.baidu.com/search/index?tn=baiduimage&amp;ps=1&amp;ct=201326592&amp;lm=-1&amp;cl=2&amp;nc=1&amp;ie=utf-8&amp;word=" wdfield="word" onmousedown="return c({‘fm‘:‘tab‘,‘tab‘:‘pic‘})">图片</a>
    <a href="http://v.baidu.com/v?ct=301989888&amp;rn=20&amp;pn=0&amp;db=0&amp;s=25&amp;ie=utf-8&amp;word=" wdfield="word" onmousedown="return c({‘fm‘:‘tab‘,‘tab‘:‘video‘})">视频</a>
    <a href="http://map.baidu.com/m?word=&amp;fr=ps01000" wdfield="word" onmousedown="return c({‘fm‘:‘tab‘,‘tab‘:‘map‘})">地图</a>
    <a href="http://wenku.baidu.com/search?word=&amp;lm=0&amp;od=0&amp;ie=utf-8" wdfield="word" onmousedown="return c({‘fm‘:‘tab‘,‘tab‘:‘wenku‘})">文库</a>
    <a href="//www.baidu.com/more/" onmousedown="return c({‘fm‘:‘tab‘,‘tab‘:‘more‘})">更多&raquo;</a>
   </div>
   <div class="qrcodeCon">
    <div id="qrcode">
     <div class="qrcode-item qrcode-item-1">
      <div class="qrcode-img"></div>
      <div class="qrcode-text">
       <p><b>手机百度</b></p>
      </div>
     </div>
    </div>
   </div>
   <div id="ftCon">
    <div class="ftCon-Wrapper">
     <div id="ftConw">
      <p id="lh"><a id="setf" href="//www.baidu.com/cache/sethelp/help.html" onmousedown="return ns_c({‘fm‘:‘behs‘,‘tab‘:‘favorites‘,‘pos‘:0})" target="_blank">把百度设为主页</a><a onmousedown="return ns_c({‘fm‘:‘behs‘,‘tab‘:‘tj_about‘})" href="http://home.baidu.com">关于百度</a><a onmousedown="return ns_c({‘fm‘:‘behs‘,‘tab‘:‘tj_about_en‘})" href="http://ir.baidu.com">About&nbsp;&nbsp;Baidu</a><a onmousedown="return ns_c({‘fm‘:‘behs‘,‘tab‘:‘tj_tuiguang‘})" href="http://e.baidu.com/?refer=888">百度推广</a></p>
      <p id="cp">&copy;2017&nbsp;Baidu&nbsp;<a href="http://www.baidu.com/duty/" onmousedown="return ns_c({‘fm‘:‘behs‘,‘tab‘:‘tj_duty‘})">使用百度前必读</a>&nbsp;<a href="http://jianyi.baidu.com/" class="cp-feedback" onmousedown="return ns_c({‘fm‘:‘behs‘,‘tab‘:‘tj_homefb‘})">意见反馈</a>&nbsp;京ICP证030173号&nbsp;<i class="c-icon-icrlogo"></i>&nbsp;<a id="jgwab" target="_blank" href="http://www.beian.gov.cn/portal/registerSystemInfo?recordcode=11000002000001">京公网安备11000002000001号</a>&nbsp;<i class="c-icon-jgwablogo"></i></p>
     </div>
    </div>
   </div>
   <div id="wrapper_wrapper">
   </div>
  </div>
  <div class="c-tips-container" id="c-tips-container"></div> 

在贴上Jsoup自身携带的常用的几个获取dom对象具体元素的方法:

method                           description
getElementsByClass()             通过Class属性来定位元素,获取的是所有带这个class属性的集合
getElementsByTag();              通过标签名字来定位元素,获取的是所有带有这个标签名字的元素结合
getElementById();                通过标签的ID来定位元素,这个是精准定位,因为页面的ID基本不会重复
getElementsByAttributeValue();   通过属性和属性名来定位元素,获取的也是一个满足条件的集合;
getElementsByAttributeValueMatching()        通过正则匹配属性

比如说我现在要获取百度首页这个title,那么我们得先确定这玩意在哪,通过查看我们发现它是id=”u”的div标签的一个子元素,那么不管那么多我们先通过这个Id取到这个对象然后在获取这个Title,下面是具体操作

//获取页面对象
String startPage="https://www.baidu.com";

Document document = Jsoup.connect(startPage).userAgent("Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/52.0.2743.116 Safari/537.36").get();

//定位元素父级
Element parentElement = document.getElementById("u");

//定位具体元素
Element titleElement = parentElement.getElementsByTag("a").get(0);

//获取所需数据
String title = titleElement.text();

System.out.println(title);

又或者我需要获取页面《手机百度》这个数据:

String startPage="https://www.baidu.com";

Document document = Jsoup.connect(startPage).userAgent("Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/52.0.2743.116 Safari/537.36").get();

Element elementById = document.getElementById("qrcode");

String text = elementById.getAllElements().get(0).getAllElements().get(1).getElementsByTag("b").text();

System.out.println(text);

这就是一个很简单的爬虫编写工具,Jsoup功能很强大,对直接爬取没有动态加载的静态资源页面再适合不过。

时间: 2024-10-11 23:16:56

Java 爬虫工具Jsoup解析的相关文章

Java爬虫利器HTML解析工具-Jsoup

Jsoup简介 Java爬虫解析HTML文档的工具有:htmlparser, Jsoup.本文将会详细介绍Jsoup的使用方法,10分钟搞定Java爬虫HTML解析. Jsoup可以直接解析某个URL地址.HTML文本内容,它提供非常丰富的处理Dom树的API.如果你使用过JQuery,那你一定会非常熟悉. Jsoup最强大的莫过于它的CSS选择器支持了.比如:document.select("div.content > div#image > ul > li:eq(2). 包

初识Java爬虫之Jsoup,提供参考代码

本文主要分享的是关于Java爬虫技术其中一个方式   ==>  Jsoup 1.Jsoup简介 推开技术大门,爬虫技术琳琅满目,而今天要分享的Jsoup是一款Java的HTML解析神器,,可直接解析某个URL地址.HTML文本内容.它提供了一套非常省力的API.可通过DOM,CSS以及类似于jQuery的操作方法来取出和操作数据. .关于Jsoup的详细介绍,不赘述,以下是 官方文档,自行查阅.我们直接上代码. 2.代码分享(真实爬取一个政府采购网:中国政府采购网,按照关键词搜索的公告) 注意的

使用java开源工具httpClient及jsoup抓取解析网页数据

今天做项目的时候遇到这样一个需求,需要在网页上展示今日黄历信息,数据格式如下 公历时间:2016年04月11日 星期一 农历时间:猴年三月初五 天干地支:丙申年 壬辰月 癸亥日 宜:求子 祈福 开光 祭祀 安床 忌:玉堂(黄道)危日,忌出行 主要包括公历/农历日期,以及忌宜信息的等.但是手里并没有现成的数据可供使用,怎么办呢? 革命前辈曾经说过,没有枪,没有炮,敌(wang)人(luo)给我们造!网络上有很多现成的在线 万年历应用可供使用,虽然没有现成接口,但是我们可以伸出手来,自己去拿.也就是

Java爬虫框架SeimiCrawler的工程自动打包工具使用

为了便于开发者对使用SeimiCrawler框架开发的爬虫工程的打包部署,SeimiCrawler现已推出maven-seimicrawler-plugin,一个maven工程的自动化打包插件.下面简要介绍下他的使用. 开始 pom添加添加plugin <plugin> <groupId>cn.wanghaomiao</groupId> <artifactId>maven-seimicrawler-plugin</artifactId> <

Java系统工具jps原理解析

Java系统工具jps原理解析 简介 当我们需要获取当前正在运行的Java进程时,我们可以通过操作系统自带的工具来筛选,如ps和netstat等.不过Java也提供了通用的工具来实现该功能,而且能够提供更加详细的信息.jps是Java Virtual Machine Process Status Too的简称,可以用来获取当前用户系统中的Java进程. 使用 jps的命令格式为 jps [ options ] [ hostid ],具体形式如下: usage: jps [-help] jps [

Java 并发工具CountDownLatch和CyclicBarrier 原理解析

[TOC] Java 并发工具CountDownLatch和CyclicBarrier 原理解析 一,简介 CountDownLatch 允许一个或者多个线程等待其他线程完成操作. CyclicBarrier 的字面意思是可循环使用(Cyclic)的屏障(Barrier).它要做的事情是,让一组线程达到一个屏障(也可以叫同步点)时被阻塞,直到最后一个线程到达屏障时,屏障才会开门,所有被屏障拦截的线程才会继续运行. 二,代码演示 CountDownLatchDemo public class Co

使用轻量级JAVA 爬虫Gecco工具抓取新闻DEMO

写在前面 最近看到Gecoo爬虫工具,感觉比较简单好用,所有写个DEMO测试一下,抓取网站 http://zj.zjol.com.cn/home.html,主要抓取新闻的标题和发布时间做为抓取测试对象.抓取HTML节点通过像Jquery选择器一样选择节点,非常方便,Gecco代码主要利用注解实现来实现URL匹配,看起来比较简洁美观. Gecoo GitHub地址 https://github.com/xtuhcy/gecco Gecoo 作者博客 http://my.oschina.net/u/

Java爬虫项目实战(一)

目的: 通过网络爬虫爬取中国最小粒度的区域维度信息,包括省(Province) .市(City).县(County).镇(town).村委会(village) 主网站链接: http://www.stats.gov.cn/tjsj/tjbz/tjyqhdmhcxhfdm/2015/index.html 主要jar包: http://jsoup.org/packages/jsoup-1.8.1.jar 之前一节我们说过java爬虫从网络上利用jsoup获取网页文本,也就是说我们可以有三种方法获取h

使用Jsoup解析网页

之前已经发表过一篇使用HtmlParser类来解析视频网站的教程 http://blog.csdn.net/gfd54gd5f46/article/details/54960538 我发现htmlparser类太旧了,而且用起来语法也不清晰. 所以我又找来一个更强大的解析网页的工具类:Jsoup 来帮助我们制作更强大的网络爬虫 下载Jsoup类       jsoup 是一款Java 的HTML解析器,可直接解析某个URL地址.HTML文本内容.它提供了一套非常省力的API,可通过DOM,CSS