htmlunit+quartz定时抓取博文并生成jsp页面

xiaoxiao2021-02-28  112

前言分析网页 页码分析文章链接分析文章内容分析 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页面。

写了一个多小时 也该回宿舍了~~希望暑期能找到个实习工作 唉

转载请注明原文地址: https://www.6miu.com/read-62442.html

最新回复(0)