声明:本文为原创,转载请注明出处

本文总共三章,前面两章废话吐槽比较多,想看结果的话,直接看第三章(后续会更新,最近忙着毕设呢,毕设也是我自己做的,关于射频卡的,有时间我也放上来,哈哈)。

  • 一,系统总体结构

  首先吐槽一下,标题取得好水,原谅我是一枚耿直的工科男。系统框图如下所示,简单看一下,对整体有个把握,总体由4个部分组成

  上图中,装载URL队列的是先进先出的队列,整个爬虫系统的设计就是基于宽度优先遍历的原则设计的。所以,对于执行整个下载任务的引擎而言,它只是启动一个线程池,然后机械的从队列里面拿出链接,下载网页,然后再将网页中的链接放到队列里面,循环上面的操作。由于每一个站点都有其自身布局的特点,比如特定的编码,特定的URL格式,面向站点的模板需要提供这些特点,以方便爬取效率和自己想要得到的效果。对于一张网页,我们真正关心的,讲个实话,只是一部分数据,所以在模板获取数据之前,是先需要对数据进行过滤,排版等相关处理的,面向数据处理的模型就是为了解决这个问题而产生的。(我去感觉这段话,有种催眠的感觉,发现自己表达能力好差。)

  •   二,设计思想及核心流程图

  说点题外话,关于爬虫的的实现,网上很多,但是只要你不是我这样的大老粗,你仔细看就会发现,所有的实现基本都是机械抓取URL,最为致命的是抓取的URL还有可能是相对URL。那什么获取个性化数据就有点大海捞针的感觉了。哈哈,自恋一下,本爬虫就可以大海捞针(你也可以当笑话看,否则这玩意太枯燥了)。其实我感觉的话,爬虫的核心无非就两个:一是要能很好的处理URL,二是方便获取想要的数据。至于什么效率,鄙人认为,在这个计算机处理能力飞速提示的年代,不是那么重要。

  下面是整个引擎执行流程图:

上图十分清楚的描述了整个引擎的执行流程图,现在一看好像很简单,但是当时写起来,那个问题,不想说了,不利于弘扬社会主义核心价值观,哈哈。至于到底是怎么用我会把代码放出来(留言qq索取也行,githup还没有建仓库呢),有了这个图大家看起来,也方便些。接下来,实在是不想废话了,直接看使用demo。

  • 三,实践

  正所谓实践是检验真理的唯一标准,这里以抓取阿里巴巴旗下蚂蚁金服的基金数据为例子,进行简单讲解一下。

  3.1 定义一个基于该网站的引擎类。此类需要导入我开发的包,然后继承自Spider。Spider有几个函数是用于子类重载的。主要的也就是下面的三个重载子函数.详情看注释

public class AliFundtion extends Spider {
private WebClient webClient=new WebClient();
private Pattern HREF=Pattern.compile("href=\"(.*?)\"");
public AliFundtion(int maxSize,int threadSize){
super(maxSize,threadSize);
initWebOptions();
}
private void initWebOptions(){
webClient.setAjaxController(new NicelyResynchronizingAjaxController());
webClient.getOptions().setJavaScriptEnabled(true);
webClient.getOptions().setCssEnabled(false);
webClient.getOptions().setTimeout(35000);
webClient.getOptions().setThrowExceptionOnScriptError(false);
} /**
* 通过重载这个函数,我们这里只抓取蚂蚁金服首页展示的基金数据,因为它首页包含了所有的基金,
* 这个函数决定了URL队列里面到底有哪些链接,是引擎的抓取的来源
* @param html 抓取到的网页
* @param url 该网页对应的URL
* @param que URL队列
*/
@Override
protected void allHrefEnQueue(String html, String url, SpiderQueue que) {
if(url.equals("http://www.fund123.cn/fund")){//断定是首页
List<String> hrefs=RegexUtil.getAllMatcher(html,1,HREF);
for(String href:hrefs){
String absoUrl=Browser.relative2TrUri(href,url);//转化为绝对路径
if(absoUrl.startsWith("http://www.fund123.cn/matiaria?fundCode")){//这正是我们需要的基金数据
que.enQueue(absoUrl);
}
}
} } /**
* 这个函数决定了,通过URL获取网页的方式,对于需要执行js代码的网页而言,重载这个函数是必须得,比如这里就是基于htmlUnit重载了Spider的这个函数
* @param url 即将抓取的URL
* @param charset 所用的字符编码
* @return 返回抓取到的数据
* @throws IOException
*/
@Override
synchronized protected String toGetHtmlPage(String url, String charset) throws IOException {
HtmlPage page=webClient.getPage(url);
return page.asXml();
} /**
* 注意这里必须调用父类的close()方法,来释放一些资源
*/
@Override
protected void close() {
super.close();
webClient.close();
}
}

  3.2 主程序调用步骤

public class Main {
public static void main(String[] args) { //step1: 创建一个你自己定义的爬虫引擎,第一个参数表示队列的最大容量,第二个参数表示开启线程池中线程数量
AliFundtion aliFundtion=new AliFundtion(50,6);
//step2:定义你自己的站点模板
ICrawlTemplate temp=new AbstractTemplate() {
@Override
public void crawlValue(String html, String url) {
//todo 在这里写下你想做的事,比如将得到的数据持久化到数据库,或者保存到磁盘,其中html表示被数据模型修饰后的数据,url是该html对应的链接
System.out.println(html);
}
@Override
public String getBaseSite() {
return "http://www.fund123.cn/fund";
} @Override
public String getCharset() {
return null;
} @Override
public boolean filterUrl(String url) {
return true;
}
};
//step3:采用正则表达式进行数据建模
//<_%></_%>这是一对表示这个一个正则表达式的标签
//index 属性 就是该正则表达式需要提取的组
StringBuilder sb=new StringBuilder();
sb.append("基金名称:").append("<_% index=\"1\">").append("<span class=\"fundmatiaria-title-fundname\">(.*?)</span>").append("</_%>");
sb.append("基金代码:").append("<_% index=\"1\">").append("<span class=\"fundmatiaria-title-fundcode\">(.*?)</span>").append("</_%>");
sb.append("基金净值:").append("<_% index=\"1\">").append("<p class=\"fundmatiaria-fundinfo-value\".*?>(.*?)</p>").append("</_%>");
RegexModel model=new RegexModel(sb.toString());
model.getOptions().setAbsoJs(true);//表示将所有js路径转化为绝对路径
model.getOptions().setAbsoImage(true);//表示将所有image路径转化为绝对路径
model.getOptions().setAbsoCss(true);//表示将所有css路径转化为绝对路径
aliFundtion.setModel(model);
//step4:下载模板
aliFundtion.downLoadArtcle(temp);
}
}

 3.3 看一下结果:

基金名称:南方原油(QDII-FOF)

基金代码:(501018)

基金净值:1.1502  +1.42%  -1.57%

基金名称:广发道琼斯美国石油开发与生产指数(QDII-LOF)A

基金代码:(162719)

基金净值:1.1371 +1.65% +0.04%

基金名称:银华心诚灵活配置混合

基金代码:(005543)

基金净值:0.9507 +1.79% +1.79%

基于http(s)协议的模板化爬虫设计的更多相关文章

  1. 基于UDP传输协议局域网文件接收软件设计 Java版

    网路传输主要的两大协议为TCP/IP协议和UDP协议,本文主要介绍基于UDP传输的一个小软件分享,针对于Java网络初学者是一个很好的练笔,大家可以参考进行相关的联系,但愿能够帮助到大家. 话不多说, ...

  2. 基于Heritrix的特定主题的网络爬虫配置与实现

    建议在了解了一定网络爬虫的基本原理和Heritrix的架构知识后进行配置和扩展.相关博文:http://www.cnblogs.com/hustfly/p/3441747.html 摘要 随着网络时代 ...

  3. 利用Aspose.Word控件和Aspose.Cell控件,实现Word文档和Excel文档的模板化导出

    我们知道,一般都导出的Word文档或者Excel文档,基本上分为两类,一类是动态生成全部文档的内容方式,一种是基于固定模板化的内容输出,后者在很多场合用的比较多,这也是企业报表规范化的一个体现. 我的 ...

  4. 读书笔记 effective c++ Item 43 了解如何访问模板化基类中的名字

    1. 问题的引入——派生类不会发现模板基类中的名字 假设我们需要写一个应用,使用它可以为不同的公司发送消息.消息可以以加密或者明文(未加密)的方式被发送.如果在编译阶段我们有足够的信息来确定哪个信息会 ...

  5. 基于JT/T808协议的车辆监控平台架构方案

    技术支持QQ:78772895 1.接入网关应用采用mina/netty+spring架构,独立于其他应用,主要负责维护接入终端的tcp链接.上行以及下行消息的解码.编码.流量控制,黑白名单等安全控制 ...

  6. 基于 Scrapy-redis 两种形式的分布式爬虫

    基于 Scrapy-redis 两种形式的分布式爬虫 .caret, .dropup > .btn > .caret { border-top-color: #000 !important ...

  7. 基于Nutch+Hadoop+Hbase+ElasticSearch的网络爬虫及搜索引擎

    基于Nutch+Hadoop+Hbase+ElasticSearch的网络爬虫及搜索引擎 网络爬虫架构在Nutch+Hadoop之上,是一个典型的分布式离线批量处理架构,有非常优异的吞吐量和抓取性能并 ...

  8. 基于TCP/IP协议的C++网络编程(API函数版)

    源代码:http://download.csdn.net/detail/nuptboyzhb/4169959 基于TCP/IP协议的网络编程 定义变量——获得WINSOCK版本——加载WINSOCK库 ...

  9. 从零開始学习制作H5应用——V5.0:懊悔机制,整理文件夹,压缩,模板化

    经过前面四个版本号的迭代.我们已经制作了一个从视觉和听觉上都非常舒服的H5微场景应用,没有看过的请戳以下: V1.0--简单页面滑动切换 V2.0--多页切换.透明过渡及交互指示 V3.0--增加lo ...

随机推荐

  1. 并发编程-concurrent指南-阻塞双端队列BlockingDeque

    java.util.concurrent 包里的 BlockingDeque 接口表示一个线程安放入和提取实例的双端队列. BlockingDeque 类是一个双端队列,在不能够插入元素时,它将阻塞住 ...

  2. [AI开发]目标跟踪之速度计算

    基于视频结构化的应用中,目标在经过跟踪算法后,会得到一个唯一标识和它对应的运动轨迹,利用这两个数据我们可以做一些后续工作:测速(交通类应用场景).计数(交通类应用场景.安防类应用场景)以及行为检测(交 ...

  3. 自己实现定制自己的专属java锁,来高效规避不稳定的第三方

    java juc 包下面已经提供了很多并发锁工具供我们使用,但在日常开发中,为了各种原因我们总是会用多线程来并发处理一些问题,然而并不是所有的场景都可以使用juc 或者java本身提供的锁来方便的帮助 ...

  4. JAVA包装类解析和面试陷阱分析

    包装类 什么是包装类 虽然 Java 语言是典型的面向对象编程语言,但其中的八种基本数据类型并不支持面向对象编程,基本类型的数据不具备“对象”的特性——不携带属性.没有方法可调用. 沿用它们只是为了迎 ...

  5. NDK_OVERVIEW翻译

    Android NDK Overview Introduction: The Android NDK is a set of tools that allows Android application ...

  6. 记录一次pycharm中,引入其他类可用,下面总是有波浪线,而且Ctrl+b 无法查看类函数的源码

    最近在玩python,发现引入其他的函数们总是有波浪线,但是能够使用,crtl+b却无法看到,非常尴尬,然后查看了原因,记录如下: This inspection detects names that ...

  7. nginx的access.log 和 error.log

    nginx 常用的配置文件有两种: access.log 和 error.log access.log 的作用是 记录用户所有的访问请求,不论状态码,包括200 ,404,500等请求,404,500 ...

  8. GeoPackage - 一个简便轻量的本地地理数据库

    GeoPackage(以下简称gpkg),内部使用SQLite实现的一种单文件.与操作系统无关的地理数据库. 当前标准是1.2.1,该版本的html版说明书:https://www.geopackag ...

  9. Excel催化剂开源第41波-网抓网络采集类库及工具分享

    在VBA开发网抓程序中,会用到xmlhttp/winHttp.winHttprequest.5.1等组件,当时笔者也是这样进入了网抓领域的,这些都是非常过时的东西,在.Net的开发中,有大量的更好用的 ...

  10. C#使用CLR/C++的DLL间接调用Native C++的DLL

    C#使用CLR/C++的DLL间接调用Native C++的DLL 开发环境:win 7  VS2010 简介:C#的exe使用CLR/C++间接调用Native C++的DLL. 第一步:创建一个C ...