WebMagic爬虫框架及javaEE SSH框架将数据保存到数据库(二)

2024-08-28 11:38

本文主要是介绍WebMagic爬虫框架及javaEE SSH框架将数据保存到数据库(二),希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

关于一些基本内容可查看上一篇博客:http://blog.csdn.net/u013082989/article/details/51176073

一、首先看一下爬虫的内容:

(1)学科类型、课程、课程对应章节、课程对应参考教材(主要是要将课程章节对应到上一级爬取的课程上,还有就是课程教材的爬取比较麻烦,下面会讲到)


课程章节:


课程教材


教材内容


二、实体类的设计:

(1)课程类、课程对应章节类(一对多),课程对应教材类(一对多),关于hibernate映射文件就不说明了。


三、爬取课程及对应章节

(1)与上篇博客一样,实现PageProcessor接口

public class CourseSpider implements PageProcessor
以及其中的方法

(2)分析学科类型,就是li标签下对应一个超链接,学科类型比较少,我是单独写了一个爬虫将其存入数据库的(其实手打都可以....)。主要是下面可以将其作为待爬取链接然后请求。


(3)然后分析课程,以哲学学科为例,链接为:域名+/category/01,但是是有分页的

点击第二页,发现链接为:域名+/category/01/2/24,所以2就对应第二页,24就是前2页的记录数


所以我们可以通过改变url地址方式,加载所有的内容。


(4)分析课程章节,就是一个li标签对应一章节,也比较简单

(5)实现代码:

1、获取所需的service

	private ApplicationContext ac = new ClassPathXmlApplicationContext("applicationContext.xml");// 获取serviceISpiderCourseService spiderCourseService = (ISpiderCourseService) ac.getBean("spiderCourseServiceImpl");ISpiderProfessionTypeService spiderProfessionTypeService = (ISpiderProfessionTypeService) ac.getBean("spiderProfessionTypeServiceImpl");ISpiderChapterService spiderChapterService = (ISpiderChapterService) ac.getBean("spiderChapterServiceImpl");ISpiderDocumentService spiderDocumentService = (ISpiderDocumentService) ac.getBean("spiderDocumentServiceImpl");
2、定义site,可以将setTimeOut设置的长一点,因为我们通过改变url访问的记录条数比较多,否则可能出现错误。
private Site site = Site.me().setRetryTimes(5).setSleepTime(3000).setTimeOut(23000);
3、process方法,满足对应的正则表达式表示进入第几层爬虫,调用对应的方法。

	@Overridepublic void process(Page page) {// 格式:http://mooc.chaoxing.com/category/01/0/1000if (page.getUrl().regex("http://mooc\\.chaoxing\\.com/category/\\d+/\\d/\\d+").toString() != null) {System.out.println("第一层");crawerCourse(page);}// 格式:http://mooc.chaoxing.com/course/55672.htmlelse if (page.getUrl().regex("http://mooc\\.chaoxing\\.com/course/\\d+\\.html").toString() != null) {System.out.println("第二层");crawCourseInfo(page);}}
4、爬取课程信息的方法:

一些解析html的就不说了,我用的xpath,WebMagic还提供了很多解析的方法。

我们将爬取的信息封装成课程对象, 并将课程的url作为待爬取的链接(及第二层),将课程对象放到request中(因为第二层爬取章节,需要找到对应的课程类),设置请求的优先级为1(数越小优先级越高,先爬取第一层,再爬取第二层)。

	/*** 爬去课程信息*/public void crawerCourse(Page page) {// <div class="label">// 哲学 </div>// 筛选专业类型String professionType = page.getHtml().xpath("//div[@class='label']/text()").toString();// <li class="ans-slow-anim">// <div class="picArea ans-slow-anim"><a href="/course/198413.html"// target="_blank">// <img// src="http://p.ananas.chaoxing.com/star/258_153c/1384413396917gvcrs.jpg"// width="178" height="109"></a>// </div>// <div class="introArea"><a href="/course/198413.html" target="_blank"// title="中华传统思想-对话先秦哲学">中华传统思想-对话先秦哲学</a></div>// <div class="introArea2" title="万献初 李景林 郭齐勇 夏可君  陈炎   武汉大学">// 万献初等// 武汉大学//// </div>// </li>// 筛选名称List<String> courseNameList = page.getHtml().xpath("//div[@class='introArea']/a/html()").all();// page.putField("courseNameList", courseNameList);// 筛选urlList<String> courseUrlList = page.getHtml().xpath("//div[@class='introArea']/a/@href").all();// page.putField("courseUrlList", courseUrlList);// 筛选信息List<String> infoList = page.getHtml().xpath("//div[@class='introArea2']/@title").all();// page.putField("infoList", infoList);if (courseNameList.size() > 0) {for (int i = 0; i < courseNameList.size(); i++) {SpiderCourse model = new SpiderCourse(courseNameList.get(i).toString().trim(), courseUrlList.get(i).toString().trim(), infoList.get(i).toString(), professionType);spiderCourseService.save(model);// Request request2=new// Request(courseUrlList.get(i)).setPriority(1).putExtra("courseModel",// model);// page.putField("model", model);// 设置优先级为1page.addTargetRequest(new Request(courseUrlList.get(i)).setPriority(1).putExtra("courseModel", model));}}List<SpiderProfessionType> list =spiderProfessionTypeService.findAll();for (int j = 2; j < list.size(); j++) {// 设置优先级为0page.addTargetRequest(new Request(list.get(j).getUrl()+"/0/1000").setPriority(0));}// List<String> urlList=new ArrayList<String>();// for(int j=2;j<list.size();j++){// urlList.add(list.get(j).getUrl()+"/0/1000");// }// //将后续urls作为请求// page.addTargetRequests(urlList);}
5、爬取课程对应的章节:

可以通过

page.getRequest().getExtra("courseModel");
得到上级设置的课程对象,每个page中是有一个request的。
	/*** 爬取课程对应的章节*/public void crawCourseInfo(Page page) {/*** 得到上级传来的model,用户保存对应的课程*/SpiderCourse courseModel = (SpiderCourse) page.getRequest().getExtra("courseModel");// <div class="mt10 f33 l g5">// <span>木结构设计</span>// </div>// 筛选课程名String courseName = page.getHtml().xpath("//div[@class='mt10 f33 l g5']/span/text()").toString();// <li class="mb15 course_section fix">// <!--<a class="wh"// href="/nodedetailcontroller/visitnodedetail?knowledgeId=789300"// target="_blank">-->// <a class="wh"// href="/nodedetailcontroller/visitnodedetail?knowledgeId=789300">// <div class="f16 chapter_index l">1.1</div>// <div class="f16 pct80 pr10 r">和的哲学(一)</div>// </a>// </li>/*** 爬取章节*/// 筛选urlList<String> chapterUrlList = page.getHtml().xpath("//li[@class='mb15 course_section fix']/a[@class='wh']/@href").all();// page.putField("chapterUrlList", chapterUrlList);// 筛选章节号List<String> chapterNumList = page.getHtml().xpath("//div[@class='f16 chapter_index l']/text()").all();// page.putField("chapterNumList", chapterNumList);// 筛选章节名List<String> chapterNameList = page.getHtml().xpath("//div[@class='f16 pct80 pr10 r']/text()").all();// page.putField("chapterNameList", chapterNameList);if (chapterUrlList.size() > 0) {for (int i = 0; i < chapterUrlList.size(); i++) {SpiderChapter model = new SpiderChapter(chapterNumList.get(i).toString(), chapterNameList.get(i).toString(),chapterUrlList.get(i).toString(), courseName,courseModel);spiderChapterService.save(model);}}}
这样爬取课程及对应的章节就完成了,后面和爬取参考教材的一块测试。


四、爬取课程对应的参考教材,这个相对复杂一点

(1)分析界面

参考教材的显示是通过一个iframe,嵌套了一个html,尝试和上面一样的方法想获取对应的信息,通过调试发现是获取不到的,它应该是通过js然后拼接的html代码,我们爬虫不会得到js执行过后的html代码,所以就比较麻烦。看网上也有一些工具可以得到js执行过后的html代码,但是肯定会降低爬取的效率。


试着获取一个div下的所有节点信息,发现会得到iframe的信息,我们看到iframe中有一个data属性,对应的是一个json格式的信息,所以它应该是通过解析这个json格式的信息,然后拼接的html代码显示参考教材。(json中的bookname,author等信息是unicode编码,刚开始我还纠结是不是获取后要转为汉字,它就是一个编码方式,不用管,获取到就行了)


还有就是json中的url地址试着访问时不对的,然后分析发送的请求发现url地址也是通过js拼接的


url信息,所以我们获取后再进行处理。分析完毕。


(2)代码:

代码其实并不多,但是分析的过程还是很麻烦的。

		/*** 爬取课程对应的章节文档 ,这个有点特殊,它是一个iframe* 并且通过分析之后得出iframe里有个data属性,是json格式的数据,然后网站再通过js拼接html代码* 汉字采用的是unicode编码*/// 得到的是json格式的字符串// 格式:// {"readurl":"http://resapi.chaoxing.com/realRead?dxid=000006873411&ssid=12553309&d=BD6EECD6198FDD693FD0E87F715B5F05",// "coverurl":"http://cover.duxiu.com/cover/Cover.dll?iid=6768656B6B696569666F3839393335393236",// "bookname":"\u5148\u79e6\u54f2\u5b66",// "author":"\u66fe\u4ed5\u793c\u7f16\u8457",// "publisher":"\u6606\u660e\u5e02\uff1a\u4e91\u5357\u5927\u5b66\u51fa\u7248\u793e",// "publishdate":"2009.09",// "id":"ext-gen1223"}List<String> allInfoList = page.getHtml().xpath("//iframe/@data").all();if (allInfoList.size() > 0) {for (int i = 0; i < allInfoList.size(); i++) {// String转为jsonJSONObject json = JSONObject.fromObject(allInfoList.get(i).toString());String realUrl = json.getString("readurl");//http://resapi.chaoxing.com/realRead?dxid=000006873411&ssid=12553309&d=BD6EECD6198FDD693FD0E87F715B5F05//连接中realRead替换为innerurl,并加上后缀&unitid=7719&readstyle=4&tp=flip&rotate=true&cpage=1realUrl = realUrl.replace("realRead", "innerurl")+ "&unitid=7719&readstyle=4&tp=flip&rotate=true&cpage=1";SpiderDocument model = new SpiderDocument(json.getString("bookname"), realUrl,json.getString("author"), json.getString("publisher"),json.getString("publishdate"),json.getString("coverurl"), courseModel);spiderDocumentService.save(model);}}
五:测试

信息对应正确。



六、总结

虽然爬虫中遇到了一些麻烦,但我还是挺享受这个过程的,并且也从中学到很多东西。

这篇关于WebMagic爬虫框架及javaEE SSH框架将数据保存到数据库(二)的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/1114659

相关文章

使用Java将DOCX文档解析为Markdown文档的代码实现

《使用Java将DOCX文档解析为Markdown文档的代码实现》在现代文档处理中,Markdown(MD)因其简洁的语法和良好的可读性,逐渐成为开发者、技术写作者和内容创作者的首选格式,然而,许多文... 目录引言1. 工具和库介绍2. 安装依赖库3. 使用Apache POI解析DOCX文档4. 将解析

Java字符串处理全解析(String、StringBuilder与StringBuffer)

《Java字符串处理全解析(String、StringBuilder与StringBuffer)》:本文主要介绍Java字符串处理全解析(String、StringBuilder与StringBu... 目录Java字符串处理全解析:String、StringBuilder与StringBuffer一、St

springboot整合阿里云百炼DeepSeek实现sse流式打印的操作方法

《springboot整合阿里云百炼DeepSeek实现sse流式打印的操作方法》:本文主要介绍springboot整合阿里云百炼DeepSeek实现sse流式打印,本文给大家介绍的非常详细,对大... 目录1.开通阿里云百炼,获取到key2.新建SpringBoot项目3.工具类4.启动类5.测试类6.测

数据库面试必备之MySQL中的乐观锁与悲观锁

《数据库面试必备之MySQL中的乐观锁与悲观锁》:本文主要介绍数据库面试必备之MySQL中乐观锁与悲观锁的相关资料,乐观锁适用于读多写少的场景,通过版本号检查避免冲突,而悲观锁适用于写多读少且对数... 目录一、引言二、乐观锁(一)原理(二)应用场景(三)示例代码三、悲观锁(一)原理(二)应用场景(三)示例

Spring Boot循环依赖原理、解决方案与最佳实践(全解析)

《SpringBoot循环依赖原理、解决方案与最佳实践(全解析)》循环依赖指两个或多个Bean相互直接或间接引用,形成闭环依赖关系,:本文主要介绍SpringBoot循环依赖原理、解决方案与最... 目录一、循环依赖的本质与危害1.1 什么是循环依赖?1.2 核心危害二、Spring的三级缓存机制2.1 三

在Spring Boot中浅尝内存泄漏的实战记录

《在SpringBoot中浅尝内存泄漏的实战记录》本文给大家分享在SpringBoot中浅尝内存泄漏的实战记录,结合实例代码给大家介绍的非常详细,感兴趣的朋友一起看看吧... 目录使用静态集合持有对象引用,阻止GC回收关键点:可执行代码:验证:1,运行程序(启动时添加JVM参数限制堆大小):2,访问 htt

SpringBoot集成Milvus实现数据增删改查功能

《SpringBoot集成Milvus实现数据增删改查功能》milvus支持的语言比较多,支持python,Java,Go,node等开发语言,本文主要介绍如何使用Java语言,采用springboo... 目录1、Milvus基本概念2、添加maven依赖3、配置yml文件4、创建MilvusClient

浅析Java中如何优雅地处理null值

《浅析Java中如何优雅地处理null值》这篇文章主要为大家详细介绍了如何结合Lambda表达式和Optional,让Java更优雅地处理null值,感兴趣的小伙伴可以跟随小编一起学习一下... 目录场景 1:不为 null 则执行场景 2:不为 null 则返回,为 null 则返回特定值或抛出异常场景

Node.js 数据库 CRUD 项目示例详解(完美解决方案)

《Node.js数据库CRUD项目示例详解(完美解决方案)》:本文主要介绍Node.js数据库CRUD项目示例详解(完美解决方案),本文给大家介绍的非常详细,对大家的学习或工作具有一定的参考... 目录项目结构1. 初始化项目2. 配置数据库连接 (config/db.js)3. 创建模型 (models/

SpringMVC获取请求参数的方法

《SpringMVC获取请求参数的方法》:本文主要介绍SpringMVC获取请求参数的方法,本文通过实例代码给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下... 目录1、通过ServletAPI获取2、通过控制器方法的形参获取请求参数3、@RequestParam4、@