? ? ? ? 今天敲代码时,一直报空值百思不得其解,明明通过set赋值了怎么还为空呢(代码为下面所示)
edusubject edusubject1 = this.oneedusubject(subjectservice,subjectdata.getonesubjectname());
if (edusubject1 == null){
edusubject1.setparentid("0");
edusubject1.settitle(subjectdata.getonesubjectname());
subjectservice.save(edusubject1);
}
system.out.println("edusubject1..." edusubject1);
????????报错原因也很简单,就是对象为null值。但因为平常很少出现会先让对象为空值时再进行添加,故导致我直接忽视掉对象赋值要在不为null或是一个新对象为前提下才能修改值,以至于在排查时一直想的是set之后,但在debug是发现诶?怎么一直到不了set之后呢,到最后才去推测可能是上面的问题(当真一点逗比哈哈)
com.alibaba.excel.exception.excelanalysisexception: cannot invoke "com.master.eduservice.entity.edusubject.setparentid(string)" because "edusubject1" is null
后面解决方法也很简单,将这个空值对象重新new一个新的对象即可解决
edusubject edusubject1 = this.oneedusubject(subjectservice,subjectdata.getonesubjectname());
if (edusubject1 == null){
edusubject1 = new edusubject();
edusubject1.setparentid("0");
edusubject1.settitle(subjectdata.getonesubjectname());
subjectservice.save(edusubject1);
}
在之前的文章中,我们已经学习了如何使用scrapy框架来编写爬虫项目,那么具体scrapy框架中底层是如何架构的呢?scrapy主要拥有哪些组件,爬虫具体的实现过程又是怎么样的呢?
为了更深入的了解scrapy的相关只是,我们需要对scrapy的架构以及scrapy中常见的组件进行了解,并熟悉scrapy爬虫项目的工作流程
架构初识
要充分的理解和使用scrapy,那么就不得不了解以下scrapy的核心架构是怎么样的,如图:
从图中我们可以看到,scrapy中组件主要包括:
scrapy引擎调度器下载器下载中间件蜘蛛(也叫做爬虫,一个scrapy项目下可能会有多个spiders爬虫文件)爬虫中间件实体管道
其中scrapy引擎为整个架构的核心。调度器、实体管道、下载器和蜘蛛等组件都通过scrapy引擎来调控。在scrapy引擎和下载器之间,可以通过一个叫下载中间件的组件进行信息的传递,在下载中间件中,可以插入一些自定义的代码来轻松扩展scrapy的功能。scrapy引擎和蜘蛛之间,也可以通过一个叫爬虫中间件的组件进行爬虫与scrapy引擎的信息传递,也同样可以插入一些自定义的代码来轻松扩展scrapy的功能。在一个scrapy项目中可以存在多个爬虫文件,在运行的时候,可以指定运行某一个爬虫文件。通过scrapy引擎可以调度下载器进行下载互联网中的网页数据,以传递给蜘蛛(爬虫)文件进行对应的处理
常用组件详解
scrapy引擎
scrapy引擎是整个scrapy架构的核心,负责控制整个数据处理流程,以及出发一些事物处理。scrapy引擎与调度器、实体管道、中间件、下载器、蜘蛛等组件都有关系,scrapy引擎处于整个scrapy框架的中心的位置,对各项组件进行控制及协调
调度器
调度器主要实现存储待爬取的网页,并确定这些网址的优先级,决定下一次爬取哪个网址等。我们可以把调度器的存储结构看成一个优先队列,调度器会从引擎中接收request请求并存入优先队列中,在队列中可能会有多个待爬取的网址,但是这些网址各自具有一定的优先级,同时调度器也会过滤掉一些重复的网址,避免重复爬取
下载器
下载器主要实现对网络上要爬取的网页资源进行高速下载,由于该组件需要通过网络进行大量数据的传输,所以该组件的压力负担一般会比其他的组件重。下载器下载了对应的网页资源后,会将这些数据传递给scrapy引擎,再由scrapy引擎传递给对应的爬虫进行处理
下载中间件
下载中间件是处于下载器与scrapy引擎之间的一个特定的组件,主要用于对下载器和scrapy引擎之间的通信进行处理,在下载中间件中,可以加入自定义代码,轻松地实现scrapy功能的扩展,我们下载中间件加入的自定义代码,会在scrapy引擎与下载器通信的时候调用
蜘蛛
蜘蛛组件,也叫做爬虫组件,该组件是scrapy框架中爬虫实现的核心。在一个scrapy项目中,可以有多个蜘蛛,每个蜘蛛可以负责一个或多个特定的网站。蜘蛛组件主要负责接收scrapy引擎中的response响应,在接收了response响应之后,蜘蛛会对这些response响应进行分析处理,然后可以提取对应的关注的数据,也可以提取出接下来需要处理的新网址等信息
爬虫中间件
爬虫中间件是处于scrapy引擎与爬虫中间件之间的一个特定的组件,主要用于对爬虫组件和scrapy引擎之间的通信进行处理。同样,在爬虫中间件可以加入一些自定义代码,轻松的实现scrapy功能的扩展。在爬虫中间件中加入的自定义代码,会在scrapy引擎与爬虫组件之间通信的时候调用
实体管道
实体管道主要用于接收从蜘蛛组件中提取出来的项目(item),接收后,会对这些item进行对应的处理,常见的处理主要有:清洗,验证,存储到数据库中等
scrapy工作流
我们已经知道了scrapy框架中主要有哪些组件,以及各项组件的具体作用有哪些,那么在运行scrapy爬虫项目的时候,各项数据处理在组件中又是怎么进行的呢?这些组件会如何配合呢?下面请看scrapy数据处理流程图,如下:
首先,scrapy引擎会将爬虫文件中设置的要爬取的起始网址(默认在start_urls属性中设置)传递到调度器中。随后,依次进行图中的1~13的过程。
第1步:过程1中,主要将下一次要爬取的网址传递给scrapy引擎,调度器是一个优先队列,里面可能存储着多个要爬取的网址(当然也可能只有一个网址),调度器会根据各网址的优先级分析出下一次要爬取的网址,然后再传递给scrapy引擎
第2步:scrapy引擎接收到过程1中传过来的网址之后,过程2scrapy引擎主要将网址传递给下载中间件
第3步:下载中间件接收到scrapy引擎传递过来的网址之后,过程3中下载中间件会将对应的网址传递给下载器
第4步:然后,下载器接收到对应要下载的网址,然后过程4会向互联网中对应的网址发送request请求,进行网页的下载
第5步:互联网中对应的网址接收到request请求之后,会有相应的response响应,随后在过程5中将响应返回给下载器
第6步:下载器接收到响应之后,即完成了对应网页的下载,随后过程6会将对应的响应传递给下载中间件
第7步:下载中间件接收到对应响应之后,会与scrapy引擎进行通信,过程7会将对应的response响应传递给scrapy引擎
第8步:scrapy引擎接收到response响应之后,过程8scrapy引擎会将response响应信息传递给爬虫中间件
第9步:爬虫中间件接收到对应响应之后,过程9爬虫中间件会将响应传递给对应的爬虫进行处理
第10步:爬虫进行处理之后,大致会有两方面的信息:提取出来的数据和新的请求信息。然后过程10爬虫会将处理后的信息传递给爬虫中间件。
第11步:爬虫中间件接收到对应信息后,过程11会将对应信息传递给scrapy引擎
第12步:scrapy引擎接收到爬虫处理后的信息之后,会同时进行过程12和过程13。在过程12中,scrapy引擎会将提取出来的项目实体(item)传递给实体管道(item pipeline),由实体管道对提取出来的信息进行进一步处理:过程13中,scrapy引擎会将爬虫处理后得到的新的请求信息传递给调度器,由调度器进行进一步网址的调度
随后,再重复执行第1 ~ 12步,即过程1 ~ 13,一直到调度器中没有网址调度或者异常退出为止
mybaits在新增里加入 on duplicate key update 实例
insert into ws_product_fun(
id,
pro_sum_id,
fun_title,
fun_desc,
fun_photo,
fun_sort,
isdel,
create_user,
create_time
)
values (
#{id},
#{prosumid},
#{funtitle},
#{fundesc},
#{funphoto},
#{funsort},
#{isdel},
#{createuser},
now()
)
on duplicate key update
pro_sum_id = #{prosumid},
fun_title = #{funtitle},
fun_desc = #{fundesc},
fun_photo = #{funphoto},
fun_sort = #{funsort},
isdel = #{isdel},
create_user = #{createuser},
create_time = #{createtime},
update_user = #{updateuser},
update_time = now()
如果同时存在主键和唯一索引,先判断主键是否重复,在判断唯一索引,都没重复就新增,有重复就修改
还没有评论,来说两句吧...