基于Jsoup实现的简单爬虫
来源:互联网 发布:大学生应知相关法律 编辑:程序博客网 时间:2024/05/17 02:44
Jsoup 概念
jsoup 是一款Java 的HTML解析器,可直接解析某个URL地址、HTML文本内容。它提供了一套非常省力的API,可通过DOM,CSS以及类似于jQuery的操作方法来取出和操作数据。
其实在这之前我解析Html一直都是使用HtmlPaser来做,在我第一次看到Jsoup的时候,我就在思考Jsoup的存在意义,既然已经有htmlPaser为什么还会Jsoup出现。经过自己动手试验了一下,我感觉到了Jsoup的魅力。
- 首先是更新频率,Htmlpaser早在06年就停止更新了,这十年间互联网技术的变化不可谓不大,htmlpaser或许现在还能勉强使用,但不保证下一刻啊。Jsoup到目前为止还在继续更新,作为一个比Htmlpaser年轻的Html解释器,或许还有很多地方不足,但在持续更新下终究会得到解决。
- 然后是实现原理, htmlpaser是基于fileter进行解析,有些类似对字符串进行正则匹配的方式进行获取。或许是我对htmlpaser还不够熟悉,在一个Paser对象进行pase一次后该paser对象将不可再使用。然而Jsoup却使用了一套自建的Dom结构,该DOM结构就是一个树形数据结构。相比htmlPaser在使用filter转换一次后将不可再次使用的问题,jsoup完全不存在这个问题,在使用getElement*方法后仅仅是获取其子树或者叶子,对原有的树并未做出任何改变。
- 然后是使用方法,而如果需要获取其子节点要么使用filter一步到位,要么就只能根据子节点层次遍历。这种不灵活的节点获取方式造成了很多垃圾代码,也使程序变得十分脆弱。然而Jsoup却使用了一套自建的Dom结构,几乎兼容javascript的dom操作方式,即可取值也可设置。更加需要说明的是jsoup有着类似jquery的dom操作方式,我相信现在绝大多数猿们都会使用jquery,这也是最吸引我的一点。
Jsoup的SSL扩展
现在很多站点都是SSL对数据传输进行加密,这也让普通的HttpConnection无法正常的获取该页面的内容,而Jsoup本身也对次没有做出相应的处理,只是留下来了一个粗糙的使用证书配置什么的方法进行解决。想了一下是否可以让Jsoup可以识别所有的SSL加密过的页面,查询了一些资料,发现可以为本地HttpsURLConnection配置一个“万能证书”,其原理是就是:
- 重置HttpsURLConnection的DefaultHostnameVerifier,使其对任意站点进行验证时都返回true
- 重置httpsURLConnection的DefaultSSLSocketFactory, 使其生成随机证书
代码实现
爬虫代码示例
package org.hanmeis.common.html;import org.jsoup.nodes.Document;import org.jsoup.nodes.Element;import org.jsoup.select.Elements;import java.io.FileWriter;import java.io.IOException;import java.net.URL;import java.util.LinkedList;import java.util.List;/** * Created by zhao.wu on 2016/12/2. * 该爬虫用于爬去奇书网的玄幻小说类表 */public class QiShuuListSpider { //用于保存小说信息的列表 static List<NovelDir> novelDirs = new LinkedList<>(); public static void main(String[] args) throws IOException { //解析过程 URL index = new URL("http://www.qisuu.com/soft/sort02/"); parsePage(index); //将信息存档 FileWriter writer = new FileWriter("qishu.txt"); for (NovelDir novelDir : novelDirs) { writer.write(novelDir.toString()); } writer.close(); } static void parsePage(URL url){ try { //使用Jsoup的解析方法进行填装Dom Document doc = Jsoups.parse(url, 1000); //获取小说列表 Elements novelList = doc.select(".listBox li"); for (Element element : novelList) { NovelDir dir = new NovelDir(); //获取小说作者 Element authorElement = element.select(".s a").first(); if(authorElement!=null) { dir.setAuthor(authorElement.html()); } //获取小说描述 Element descriElement = element.select(".u").first(); if(descriElement!=null) { dir.setDescription(descriElement.html()); } //获取标题、目录地址和封面 Element titleElement = element.select("a").last(); if(titleElement!=null) { dir.setTitle(titleElement.html()); dir.setIndexUrl(titleElement.attr("abs:href")); Element imageElement = titleElement.select("img").first(); if(imageElement!=null) { dir.setHeadPic(imageElement.attr("src")); } } System.out.println(dir); novelDirs.add(dir); } //获取下一页的地址,并进行请求 Elements pageDiv = doc.select(".tspage a"); for (Element element : pageDiv) { if(element.html().equals("下一页")){ //使用“abs:href"获取该页面的绝对地址 String path = element.attr("abs:href"); //由于该站点做了请求频率限制,过快的请求会遭到暂时屏蔽,所以要细水长流的的慢慢请求 Thread.sleep(2000); parsePage(new URL(path)); } } } catch (IOException e) { System.out.println(url); e.printStackTrace(); } catch (InterruptedException e) { e.printStackTrace(); } } /** * 小说MATE数据对象 */ static class NovelDir{ //封面 private String headPic; //作者 private String author; //标题 private String title; //目录地址 private String indexUrl; //大概描述 private String description; //getter, setter toString }}
SSL扩展代码
package org.hanmeis.common.html;import org.jsoup.Connection;import org.jsoup.helper.HttpConnection;import org.jsoup.nodes.Document;import javax.net.ssl.*;import java.io.IOException;import java.net.URL;import java.security.SecureRandom;import java.security.cert.CertificateException;import java.security.cert.X509Certificate;/** * Created by zhao.wu on 2016/11/29. */public class Jsoups{ static{ try { //重置HttpsURLConnection的DefaultHostnameVerifier,使其对任意站点进行验证时都返回true HttpsURLConnection.setDefaultHostnameVerifier(new HostnameVerifier() { public boolean verify(String hostname, SSLSession session) { return true; } }); //创建随机证书生成工厂 SSLContext context = SSLContext.getInstance("TLS"); context.init(null, new X509TrustManager[] { new X509TrustManager() { public void checkClientTrusted(X509Certificate[] chain, String authType) throws CertificateException { } public void checkServerTrusted(X509Certificate[] chain, String authType) throws CertificateException { } public X509Certificate[] getAcceptedIssuers() { return new X509Certificate[0]; } } }, new SecureRandom()); //重置httpsURLConnection的DefaultSSLSocketFactory, 使其生成随机证书 HttpsURLConnection.setDefaultSSLSocketFactory(context.getSocketFactory()); } catch (Exception e) { e.printStackTrace(); } } /** * 使用ssl的方式去获取远程html的dom, * 该方法在功能上与Jsoup本身的转换工具一样, * 仅仅是用来告诉代码阅读者这个方法已经对SSL进行了扩展 * @param url 需要转换的页面地址 * @param timeoutMillis 请求超市时间 * @return 该页面的dom树 * @throws IOException 请求异常或者转换异常时抛出 */ public static Document parse(URL url, int timeoutMillis) throws IOException { Connection con = HttpConnection.connect(url); con.timeout(timeoutMillis); return con.get(); } }
0 0
- 基于Jsoup实现的简单爬虫
- 基于Jsoup实现的简单网络爬虫
- Jsoup实现简单的爬虫
- Jsoup-实现简单的网络爬虫
- 基于Crawler4j + jsoup实现爬虫
- Jsoup 实现的基于列表-详情结构的网页爬虫
- 【正完成】Java基于Jsoup的网络爬虫工具实现
- 简单的网络爬虫实现(Jsoup使用)
- 【1】用jsoup来实现简单的java爬虫
- 基于crawler4j、jsoup、javacsv的爬虫实践
- 基于crawler4j、jsoup、javacsv的爬虫实践
- 基于crawler4j、jsoup、javacsv的爬虫实践
- 基于crawler4j、jsoup、javacsv的爬虫实践
- 基于crawler4j、jsoup、javacsv的爬虫实践
- Java爬虫学习:利用HttpClient和Jsoup库实现简单的Java爬虫程序
- JAVA爬虫--Jsoup的简单运用
- JAVA简单爬虫例子--Jsoup的运用
- 非常简单Jsoup爬虫
- 利用ImageView + fragment 实现类似QQ消息界面的 点击不同按钮 展示不同界面
- cocos2d-x 学习笔记 第一日
- 安卓复习之旅—style和theme的作用及用法
- Android动态修改icon--让你的app浪起来
- 【面试题】 迅雷2014校园招聘笔试题
- 基于Jsoup实现的简单爬虫
- caffe学习笔记(一)——caffe环境安装
- 情感计算
- 签名类型
- java烧脑系列-1
- 一次理解iOS证书配置流程,再也不用查教程
- Ajax跨域请求,Json与Jsonp
- 使用开源软件sentry来收集日志
- 强大的数据库ORM框架-GreenDao项目源码剖析篇