htmlunit+quartz定时抓取博文并生成jsp页面
- 前言
- 分析网页
- 页码分析
- 文章链接分析
- 文章内容分析
- io流生成jsp页面
- squarz设置定时抓取
前言
看视频看的累了 写写博文~
很久以前就想有个自己的博客。csdn很好,可是我不是专家啊,还是功底不够, 没有权限,也就不能实现自己的一些想法。所以就百度了一个静态模版。有了模版,问题来了。是个空壳子啊,没有任何内容,所以就想着爬取自己csdn上面的所有文章并生成相应的jsp页面保存到本地,而且为了实时保证自己的博文新鲜度所以就用spring-quartz定时器定时执行抓取页面的任务。博客地址(http://www.susulovefreedom.cn)
分析网页
分析完网页,我终于发现为啥我的博文总是那么轻易的被别人爬走了 , 百度搜索排名还在我的前面。原来那么简单
页码分析
http://blog.csdn.net/su20145104009?viewmode=contents
在这个页面我们可以看到最短的分页信息。
然后通过审查元素定位到这里。
仔细查看,最大页码为12.在id为papelist标签下的第一个span元素。所以最大页码就可以这样获得
HtmlPage page=wc.getPage("http://blog.csdn.net/su20145104009?viewmode=contents");DomElement pageList = page.getElementById("papelist");//最大页码int MaxPage=Integer.parseInt(pageList.getFirstChild().asText().substring(6, 8));
文章链接分析
在上一步,我们得到了分页的最大页码。
通过查看url可以发现http://blog.csdn.net/su20145104009/article/list/2
最后一位
即为你要请求的页码。
那么就可以通过get请求来获得某一页的数据。
page=wc.getPage(“http://blog.csdn.net/su20145104009/article/list/“+MaxPage);
而在进入某一页后。继续查看源码
可以发现所有的文章都在article_list标签内。
所以我们可以首先获得article_list标签。
DomElement article_list = page.getElementById(“article_list”);
在article_list 标签内我们要继续获得文章的信息。
首先获得所有的article_list 子标签(并不包括子标签的子标签)。即上述图片的
DomNodeList<DomNode> childNodes = article_list .getChildNodes();
然后通过for循环对每一篇的文章细节进行分析:
for (DomNode htmlElement : childNodes)
文章的所有信息一览无余。
由于里面只有两个a标签。
- 在第一个a标签里面有文章的地址,标题信息。
- 在第二个a标签里面有文章的阅读次数信息。然后第二个a标签的父标签的父标签下的第一个标签内有文章的创建日期信息。
- 在获得题目的同时,使用md5码对文章的标题进行加密作为数据库中的主键
所以通过标签名字获取两个a标签:
DomNodeList<HtmlElement> links = ((DomElement) htmlElement).getElementsByTagName("a");
String address=links.get(0).getAttribute("href");String title=links.get(0).asText();String readCounts=links.get(1).getParentNode().asText();String time=links.get(1).getParentNode().getParentNode().getFirstChild().asText();
到了这一步仅仅获得了所有文章的题目信息。
那么应该如何获得文章的具体内容呢?
文章内容分析
定位到某一篇文章。通过审查元素,我们可以找到所有的文章内容都在article_details标签里。
剩下的就是把article_details标签的所有内容存到自己的网页了。
在这里遇到了一问题。
起初我使用的是htmlunit工具直接通过getElementById的方法获取article_details的源码。可以生成后的网页分析后发现。所有的文章是正常显示了,可是代码出现严重的换行现象。通过对比源码后发现,htmlunit的axXml方法会自动对所有的标签进行格式化操作。google许久也没有找到适当的解决办法。灵光一闪,想到了URLConnection。
URLConnection的get请求获得的源码和浏览器源码一致。
于是定义了一个方法。对获得的源码进行字符串截取即可。正则表达式不是我不用,是爆栈啦~字符串太长了。。。。
/*** * @Title: getArticle* @Description: (通过URLConnection的get请求获得文章的源码信息)* @param link 文章的链接* @return String 文章的源码*/public static String getArticle(String link){URL url=null;URLConnection conn=null;InputStream is = null; //字符流 InputStreamReader isr = null; //缓冲流 BufferedReader br = null; try {url=new URL(link);conn= url.openConnection();conn.setRequestProperty("User-Agent","Mozilla/4.0 (compatible; MSIE 5.0; Windows NT; DigExt)"); conn.connect();//网页编码 String context = null; //获得网页的字节输入流 is = conn.getInputStream(); //将字节输入流转换为字符输入流 并设置转码格式为utf-8 isr = new InputStreamReader(is, "utf-8"); //将字符流转换为缓冲流 br = new BufferedReader(isr); //一行一行读取网页内容 context = br.readLine(); String txt="";while ((txt=br.readLine())!=null) { context +=txt+"\n"; } int st=context.indexOf("<div id=\"article_content\"");int ed=context.indexOf("<!-- Baidu Button BEGIN -->");return context.substring(st, ed);} catch (Exception e) {if(is!=null){try {is.close();} catch (IOException e1) {throw new RuntimeException(e1);}}if(isr!=null){try {isr.close();} catch (IOException e1) {throw new RuntimeException(e1);}}if(br!=null){try {br.close();} catch (IOException e1) {throw new RuntimeException(e1);}}throw new RuntimeException(e);}
到了这里基本就快完成了~
剩下的就是使用io流写入网页了
io流生成jsp页面
我们的jsp页面肯定不能只有个文章的信息。当然也需要一些其它的元素。所以这些其它元素就需要我们自己准备了,保存到web项目里,然后使用io流读取即可。由于至少需要读取两个部分。所以我新建了一个方法
/*** * @Title: getHeadHtml* @Description: (通过文件的路径读取相应的文件信息并返回)* @param path 文件路径* @return String 文件内的信息* @throws*/public static String getHeadHtml(String path) {String res="";BufferedReader br=null;String data=null;try {br=new BufferedReader(new InputStreamReader(new FileInputStream(path),"utf-8"));while((data=br.readLine())!=null){res+=data+"\n";}} catch (IOException e) {throw new RuntimeException(e);}finally{if(br!=null){try {br.close();} catch (IOException e) {e.printStackTrace();}}}return res;}
然后就是写入jsp信息了。如果当前数据库中没有这篇文章,那么就生成这个jsp页面。jsp的名称我使用的是文章题目md5码的后8位
if(!articleService.findArticleById(id)){//将源码写入到文件OutputStreamWriter bw=new OutputStreamWriter(new FileOutputStream(filePath+"articles/"+htmlname+".jsp"),"utf-8");//jsp的头部信息bw.write(MyStringUtil.getHeadHtml(filePath+"headHtml.txt"));//head标签中的title标签bw.write("<title>"+title+"</title>");//head标签中的标题信息bw.write("<meta name=\"description\" content=\"");bw.write(content+"\" />");bw.write("<base href=\"<%=basePath%>articleShow_"+htmlname+".html\"/>");//文章内容前的信息 一些js文件css文件啦bw.write(MyStringUtil.getHeadHtml(filePath+"titlePreHtml.txt"));bw.write(title+"</a></h3>");//通过文章的链接 调用getArticle方法获得文章的源码 并写入jsp页面bw.write(MyStringUtil.getArticle(article.getLink()));//文章底部的信息bw.write(MyStringUtil.getHeadHtml(filePath+"endHtml.txt"));bw.flush();bw.close();System.out.println(title+"制作网页完成");}
到了这里就大功告成了。
squarz设置定时抓取
配置如下:每12个小时执行一次抓取任务
如果对squarz定时器不懂,请转http://blog.csdn.net/su20145104009/article/details/72842526
<!-- 任务bean 由于我要写入数据库 所有注入了articleService --><bean id="hourWork" class="com.scx.hourwork.HourWork"><property name="articleService" ref="articleService"></property></bean><!-- 使用MethodInvokingJobDetailFactoryBean,任务类可以不实现Job接口,targetObject:调用类targetMethod:调用方法--> <bean id="methodInvokingBean" class="org.springframework.scheduling.quartz.MethodInvokingJobDetailFactoryBean"><property name="targetObject" ref="hourWork"></property><property name="targetMethod" value="execute"></property></bean><!-- 任务触发器 --><bean id="myTriggers" class="org.springframework.scheduling.quartz.CronTriggerBean"><property name="jobDetail" ref="methodInvokingBean"></property><!-- 每隔12个小时更新一次 --><property name="cronExpression" value="00 00 0/12 * * ?"></property></bean><!-- 任务调度工厂 --><bean class="org.springframework.scheduling.quartz.SchedulerFactoryBean"><!-- 可以使用list配置多个,第一种方式已经演示 --><property name="triggers" ref="myTriggers"></property></bean>
执行后可以在文件夹中查看
当点击自己文章的链接时,去文章id的后8位转向这个jsp页面。
写了一个多小时 也该回宿舍了~~希望暑期能找到个实习工作 唉
htmlunit+quartz定时抓取博文并生成jsp页面相关推荐
- python 定时自动爬取_python实现scrapy爬虫每天定时抓取数据的示例代码
1. 前言. 1.1. 需求背景. 每天抓取的是同一份商品的数据,用来做趋势分析. 要求每天都需要抓一份,也仅限抓取一份数据. 但是整个爬取数据的过程在时间上并不确定,受本地网络,代理速度,抓取数据量 ...
- python定时爬取数据_python实现scrapy爬虫每天定时抓取数据的示例代码
1. 前言. 1.1. 需求背景. 每天抓取的是同一份商品的数据,用来做趋势分析. 要求每天都需要抓一份,也仅限抓取一份数据. 但是整个爬取数据的过程在时间上并不确定,受本地网络,代理速度,抓取数据量 ...
- 实现从淘宝(天猫)定时抓取订单数据、打印电子面单并保存到ERP表中
实现从淘宝(天猫)定时抓取订单数据.打印电子面单并保存到ERP表中 前言 实现思路 代码片段参考 前言 最近有厂商提出想把天猫店铺的数据拿到后台ERP管理系统中,并能实现线下打印电子面单功能.接手这个 ...
- 记一次批量定时抓取微信公众号文章的实现
记一次批量定时抓取微信公众号文章的实现 抓取前的说明和准备 数据的抓取 批量抓取 定时抓取 对爬虫防抓取机制的一些解决办法 最后 抓取前的说明和准备 本次抓取的选择的语言是java,本文章不会将整个工 ...
- python自动抓取网管软件的数据_python实现scrapy爬虫每天定时抓取数据的示例代码...
1. 前言. 1.1. 需求背景. 每天抓取的是同一份商品的数据,用来做趋势分析. 要求每天都需要抓一份,也仅限抓取一份数据. 但是整个爬取数据的过程在时间上并不确定,受本地网络,代理速度,抓取数据量 ...
- python实现scrapy爬虫每天定时抓取数据
python实现scrapy爬虫每天定时抓取数据 1. 前言. 1.1. 需求背景. 每天抓取的是同一份商品的数据,用来做趋势分析. 要求每天都需要抓一份,也仅限抓取一份数据. 但是整个爬取数据的过程 ...
- python爬虫定时抓取数据
python爬虫定时抓取数据 from scrapy import cmdline import datetime import time def doSth(): # 把爬虫程序放在这个类中 shi ...
- id 怎么获取jira 评论_一篇文章教会你使用Python定时抓取微博评论
[Part1--理论篇] 试想一个问题,如果我们要抓取某个微博大V微博的评论数据,应该怎么实现呢?最简单的做法就是找到微博评论数据接口,然后通过改变参数来获取最新数据并保存.首先从微博api寻找抓取评 ...
- .NET Core 实现定时抓取博客园首页文章信息并发送到邮箱
前言 大家好,我是晓晨.许久没有更新博客了,今天给大家带来一篇干货型文章,一个每隔5分钟抓取博客园首页文章信息并在第二天的上午9点发送到你的邮箱的小工具.比如我在2018年2月14日,9点来到公司我就 ...
最新文章
- 巨潮网怎么下载年报_上海注册公司后如何下载电子营业执照
- [转][Timer学习]wall time和monotonic time
- 记一次云安全的安全事件应急响应
- buuctf(misc) FLAG [LSB隐写]
- [转]C#中得到程序当前工作目录和执行目录的一些方法
- sketch放入app组件_使用Sketch App设计CSS网格
- Linux 命令之 iwconfig 命令-配置无线网络接口
- 系统辨识理论及应用_企业战略分析的理论工具
- 两边放动物对战守城的游戏_疯狂动物园小程序游戏:入口
- 硬盘的老化测试软件,固态硬盘不耐用?教你检测固态硬盘还能用多久
- 地址转换函数(点分十进制与网络字节序的二进制)
- 在 uniapp 中使用阿里图标
- CCSK云安全认证-M2-云基础设施安全
- 前端可视化的四种方式
- Laravel 生成QRCODE
- 深度搜索算法(DFS)
- 使用 Windows XP 的外观风格
- 基于SSM的花店系统
- 如何将word文档内容在网页显示方法
- 星聚宝—云服务器快速搭建网站(阿里云服务器举例)
热门文章
- 如何更好使用markdown输出pdf
- Python挑战游戏( PythonChallenge)闯关之路Level- 3
- Unity3D 2D射击小游戏瞄准线的实现
- Window 10 电源高性能模式设置
- 平面桁架静力计算程序
- c++成员变量初始化
- ubuntu16.04修改DNS永久生效
- 如何解决Error running ‘Tomcat 8.5.45‘: port out of range:-1
- Java Scaner类详解_动力节点Java学院整理
- 动态内存的申请和非动态内存的申请_公安交管新举措咋解读?非营运七座车6年免检,70岁可申请驾照...