Java 爬虫工具Jsoup详解

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="/" rel="external nofollow" >百度首页</a>
   <a href="javascript:;" rel="external nofollow" name="tj_settingicon" class="pf">设置<i class="c-icon c-icon-triangle-down"></i></a>
   <a href="https://passport.baidu.com/v2/?login&tpl=mn&u=http%3A%2F%2Fwww.baidu.com%2F" rel="external nofollow" rel="external nofollow" name="tj_login" class="lb" onclick="return false;">登录</a>
   </div>
   <div id="u1">
   <a href="http://news.baidu.com" rel="external nofollow" name="tj_trnews" class="mnav">新闻</a>
   <a href="http://www.hao123.com" rel="external nofollow" name="tj_trhao123" class="mnav">hao123</a>
   <a href="http://map.baidu.com" rel="external nofollow" name="tj_trmap" class="mnav">地图</a>
   <a href="http://v.baidu.com" rel="external nofollow" name="tj_trvideo" class="mnav">视频</a>
   <a href="http://tieba.baidu.com" rel="external nofollow" name="tj_trtieba" class="mnav">贴吧</a>
   <a href="http://xueshu.baidu.com" rel="external nofollow" name="tj_trxueshu" class="mnav">学术</a>
   <a href="https://passport.baidu.com/v2/?login&tpl=mn&u=http%3A%2F%2Fwww.baidu.com%2F" rel="external nofollow" rel="external nofollow" name="tj_login" class="lb" onclick="return false;">登录</a>
   <a href="http://www.baidu.com/gaoji/preferences.html" rel="external nofollow" name="tj_settingicon" class="pf">设置</a>
   <a href="http://www.baidu.com/more/" rel="external nofollow" 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&rn=20&tn=news&word=" rel="external nofollow" wdfield="word" onmousedown="return c({'fm':'tab','tab':'news'})">新闻</a>
  <a href="http://tieba.baidu.com/f?kw=&fr=wwwt" rel="external nofollow" wdfield="kw" onmousedown="return c({'fm':'tab','tab':'tieba'})">贴吧</a>
  <a href="http://zhidao.baidu.com/q?ct=17&pn=0&tn=ikaslist&rn=10&word=&fr=wwwt" rel="external nofollow" wdfield="word" onmousedown="return c({'fm':'tab','tab':'zhidao'})">知道</a>
  <a href="http://music.baidu.com/search?fr=ps&ie=utf-8&key=" rel="external nofollow" wdfield="key" onmousedown="return c({'fm':'tab','tab':'music'})">音乐</a>
  <a href="http://image.baidu.com/search/index?tn=baiduimage&ps=1&ct=201326592&lm=-1&cl=2&nc=1&ie=utf-8&word=" rel="external nofollow" wdfield="word" onmousedown="return c({'fm':'tab','tab':'pic'})">图片</a>
  <a href="http://v.baidu.com/v?ct=301989888&rn=20&pn=0&db=0&s=25&ie=utf-8&word=" rel="external nofollow" wdfield="word" onmousedown="return c({'fm':'tab','tab':'video'})">视频</a>
  <a href="http://map.baidu.com/m?word=&fr=ps01000" rel="external nofollow" wdfield="word" onmousedown="return c({'fm':'tab','tab':'map'})">地图</a>
  <a href="http://wenku.baidu.com/search?word=&lm=0&od=0&ie=utf-8" rel="external nofollow" wdfield="word" onmousedown="return c({'fm':'tab','tab':'wenku'})">文库</a>
  <a href="//www.baidu.com/more/" rel="external nofollow" onmousedown="return c({'fm':'tab','tab':'more'})">更多»</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" rel="external nofollow" 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" rel="external nofollow" >关于百度</a><a onmousedown="return ns_c({'fm':'behs','tab':'tj_about_en'})" href="http://ir.baidu.com" rel="external nofollow" >About  Baidu</a><a onmousedown="return ns_c({'fm':'behs','tab':'tj_tuiguang'})" href="http://e.baidu.com/?refer=888" rel="external nofollow" >百度推广</a></p>
   <p id="cp">©2017 Baidu <a href="http://www.baidu.com/duty/" rel="external nofollow" onmousedown="return ns_c({'fm':'behs','tab':'tj_duty'})">使用百度前必读</a> <a href="http://jianyi.baidu.com/" rel="external nofollow" class="cp-feedback" onmousedown="return ns_c({'fm':'behs','tab':'tj_homefb'})">意见反馈</a> 京ICP证030173号 <i class="c-icon-icrlogo"></i> <a id="jgwab" target="_blank" href="http://www.beian.gov.cn/portal/registerSystemInfo?recordcode=11000002000001" rel="external nofollow" >京公网安备11000002000001号</a> <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功能很强大,对直接爬取没有动态加载的静态资源页面再适合不过。

感谢阅读,希望能帮助到大家,谢谢大家对本站的支持!

(0)

相关推荐

  • Java实现爬虫给App提供数据(Jsoup 网络爬虫)

    一.需求 最近基于 Material Design 重构了自己的新闻 App,数据来源是个问题. 有前人分析了知乎日报.凤凰新闻等 API,根据相应的 URL 可以获取新闻的 JSON 数据.为了锻炼写代码能力,笔者打算爬虫新闻页面,自己获取数据构建 API. 二.效果图 下图是原网站的页面 爬虫获取了数据,展示到 APP 手机端 三.爬虫思路 关于App 的实现过程可以参看这几篇文章,本文主要讲解一下如何爬虫数据. Android下录制App操作生成Gif动态图的全过程 :http://www

  • Java爬虫Jsoup+httpclient获取动态生成的数据

    Java爬虫Jsoup+httpclient获取动态生成的数据 前面我们详细讲了一下Jsoup发现这玩意其实也就那样,只要是可以访问到的静态资源页面都可以直接用他来获取你所需要的数据,详情情跳转-Jsoup爬虫详解,但是很多时候网站为了防止数据被恶意爬取做了很多遮掩,比如说加密啊动态加载啊,这无形中给我们写的爬虫程序造成了很大的困扰,那么我们如何来突破这个梗获取我们急需的数据呢, 下面我们来详细讲解一下如何获取 String startPage="https://item.jd.com/1147

  • Java 爬虫工具Jsoup详解

    Java 爬虫工具Jsoup详解 Jsoup是一款 Java 的 HTML 解析器,可直接解析某个 URL 地址.HTML 文本内容.它提供了一套非常省力的 API,可通过 DOM,CSS 以及类似于 jQuery 的操作方法来取出和操作数据. jsoup 的主要功能如下: 1. 从一个 URL,文件或字符串中解析 HTML: 2. 使用 DOM 或 CSS 选择器来查找.取出数据: 3. 可操作 HTML 元素.属性.文本: jsoup 是基于 MIT 协议发布的,可放心使用于商业项目. js

  • Java FileUploadUtil工具类详解

    本文实例为大家分享了FileUploadUtil工具类的具体代码,供大家参考,具体内容如下 package com.gootrip.util; import java.io.File; import java.util.*; import org.apache.commons.fileupload.*; import javax.servlet.http.HttpServletRequest; import java.util.regex.Pattern; import java.io.IOEx

  • Java TimedCache 带时间缓存工具类详解使用

    简述 我们在工作中会碰到需要使用带过期时间的缓存场景.但是使用redis有太重了,毕竟缓存的数据很小,放在内存够够的.hutools提供了TimedCache时间缓存工具,可以实现该场景.下面使用到该组件,并为了适配工作场景,对该工具类做优化升级. Maven依赖 <dependency> <groupId>cn.hutool</groupId> <artifactId>hutool-all</artifactId> <version>

  • Java项目常见工具类详解

    目录 JWT工具类 MD5工具类 视频点播工具类 公共常量工具类 日期操作工具类 Http客户端工具类 获取IP工具类 JWT工具类 这里一共涉及四个方法: 传入用户信息获得token 传入token字符串判断token是否存在与有效 传入HttpServletRequest,通过获取Header中的token判断是否存在与有效 根据token获取用户id public class JwtUtils { //token过期时间 public static final long EXPIRE =

  • Java调用Oracle存储过程详解

    Java调用Oracle存储过程详解 步骤: 1.编写Oracle存储过程 2.编写数据库获取连接工具类 3.编写简单应用调用存储过程 实现: 1.Oracle存储过程: /*测试表*/ create table test( id varchar2(32), name varchar2(32) ); /*存储过程 插入数据*/ CREATE OR REPLACE PROCEDURE insert_procedure( PARA1 IN VARCHAR2, PARA2 IN VARCHAR2 )

  • Java计算数学表达式代码详解

    Java字符串转换成算术表达式计算并输出结果,通过这个工具可以直接对字符串形式的算术表达式进行运算,并且使用非常简单. 这个工具中包含两个类 Calculator 和 ArithHelper Calculator 代码如下: import java.util.Collections; import java.util.Stack; /** * 算数表达式求值 * 直接调用Calculator的类方法conversion() * 传入算数表达式,将返回一个浮点值结果 * 如果计算过程错误,将返回一

  • java解析JSON数据详解

    JSON是目前最流行的轻量级数据交换语言(没有之一).尽管他是javaScript的一个子集.但由于其是独立与语言的文本格式,它几乎可以被所有编程语言所支持. 以下是对java语言中解析json数据的总结. 要解析json,首先要导入解析json的工具类. import org.json.JSONArray; import org.json.JSONException; import org.json.JSONObject; 我们都知道JSON中有json对象与json数组(json数据就是js

  • java ThreadLocal使用案例详解

    本文借由并发环境下使用线程不安全的SimpleDateFormat优化案例,帮助大家理解ThreadLocal. 最近整理公司项目,发现不少写的比较糟糕的地方,比如下面这个: public class DateUtil { private final static SimpleDateFormat sdfyhm = new SimpleDateFormat( "yyyyMMdd"); public synchronized static Date parseymdhms(String

  • 使用正则表达式实现网页爬虫的思路详解

    网页爬虫:就是一个程序用于在互联网中获取指定规则的数据. 思路: 1.为模拟网页爬虫,我们可以现在我们的tomcat服务器端部署一个1.html网页.(部署的步骤:在tomcat目录的webapps目录的ROOTS目录下新建一个1.html.使用notepad++进行编辑,编辑内容为: ) 2.使用URL与网页建立联系 3.获取输入流,用于读取网页中的内容 4.建立正则规则,因为这里我们是爬去网页中的邮箱信息,所以建立匹配 邮箱的正则表达式:String regex="\w+@\w+(\.\w+

  • JSON在Java中的相互转换示例详解

    什么是JSON? JSON (JavaScript Object Notation) 是一种轻量级的数据交换格式. 易于人阅读和编写.同时也易于机器解析和生成. JSON采用完全独立于语言的文本格式,而且很多语言都提供了对json的支持(包括C, C++, C#, Java, JavaScript, Perl, Python等). 这样就使得JSON成为理想的数据交换格式. 数据交换格式,是指客户端和服务器之间通信,传递数据时,数据使用的格式是json JSON在java中的使用 json在ja

随机推荐