开发者学堂课程【大数据实战项目:反爬虫系统(Lua+Spark+Redis+Hadoop 框架搭建)第五阶段:爬虫识别-IP 段统计-代码实现及效果】学习笔记,与课程紧密联系,让用户快速学习知识。
课程地址:https://developer.aliyun.com/learning/course/673/detail/11696
爬虫识别-IP段统计-代码实现及效果
目录:
一、IP 段统计代码实现
二、执行效果
一、IP 段统计代码实现
5分钟时间范围内 IP 的访问量思路已经写完
object coreRule {
//1 按 IP 段聚合 -5分钟内的 IP 段(IP 前两位)访问量
def ipBlockCounts(processedData:DStream[ProcessedData]):Unit=
//抽取出数据中的 IP
数据在 processedData 里面的类型是 processedData,拿到数据调用 foreach 或 map 取决于要不要返回数据,在需求中需要返回数据,方法调用需要拿到结果,调用 map。
map 拿到一条一条数据 message,拿到数据抽取数据中的 IP。message 类型为 ProcessedD
ata,ProcessedData 里面是样例类,直接调用点,message. 第一个 remoteAddr 是用户端上的 IP,serverAddr 服务器端。使用用户端,拿到用户 IP 接收。
ProcessedData.map(message)=>{
//抽取出数据中的 IP
val ip=message.remoteAddr
//截取出 ip 的前两位
以192.168.56.151为例,IP 端为196.168。
通过点的方式截取,第一个点直接 index,最后一个点 last index,中间点如果通过截取长度,长度不一定不可以。
定一个变量 one 第一个点位置,通过第一个点找到第二个点位置,通过位置找。第一个点在 IP 当中.indexOf.
定一个变量 two 在 IP 当中.indexOf 第二个点,第一个点位置+1为第二个点位置。
IP 端截取用 IP.substring 从0开始截到第二个点位置,定变量 ipblock
//192.168.56.151 196.168
//获得到第一个.的位置
val one =ip.indexof(".")
//获得到第二个.的位置
val two =ip.indexof( str = ".",one+1)
//ip段的截取
val ipblock= ip.substring(0,two)
//将前两位作为 key,1作为 value 输出
IP 段 ipblock,1作为 value 输出。
调用 map 循环遍历,有多条数据输出多个值,拿到 key value list,需求是 IP 段被访问的总量类似于单词出现了多少次,直接调用 reduceByKey,key 为 IP 段,1为 value,调用 reduceByKey 可以拿到。
//调用 reduceByKeyAndWindow 计算最终每个ip段的总量
调用 reduceByKey 不行,只是批次的计算,时间范围在5分钟内,需求在很短时间范围内周期性计算大的时间段内的业务需求,用 reduceByKeyAndWindow 需要传入窗口,设置。
参数 reduceByKey 两位数求和,先有两位数a和b,a和b设置类型为 Int,做a+b操作。
报红因为缺少函数参数,窗口函数业务需求5分钟内而不是2秒中迭代一次,传入窗口宽度参数暂时6秒钟,滑动窗口的步长2秒。
前面定义变量接收,返回,变量为 ipblockCounts,ipblockCounts 返回
val ipBlockCounts=processedData.map(message=>{
//抽取出数据中的 IP
val ip= message.remoteAddr
//截取出 ip 的前两位
//192.168.56.151 192.168
//获得到第一个.的位置
val one =ip.indexof(".")
//获得到第二个.的位置
val two =ip.indexof(str=".",one+1)
//ip 段的截取
val ipblock= ip.substring(0,two)
//将前两位作为 key,1作为v alue,输出
(ipblock,1)
}).reduceByKeyAndwindow((a:Int,b:Int)=>a+b,Seconds(6)seconds(2))/
/调用 reduceByKeyAndwindow计算最终每个ip段的总量
ipBlockcounts
//将最终数据转换为 Map,便于后续提取、使用。
方法定义变量进行接收叫做 ipblockCounts 刚刚计算的结果转换为 map。
计算 IP 段总量,拿到 IP 段数量、某一 IP 总数,计算的结果是 IP 和量两个值,一个 key 为 IP,value 为 IP 对应总量数。
IP 量计算出后拿到每一条数据抽出 IP,每个 map 找 IP,要获取 IP 对应的值、总数。封装为 map 后 key 是 IP,value 是值,拿到 IP 去 key 很方便拿到。为了方便后续计算转换为 map
定义 ipblockCountsMap 给空的 null 做接收,循环.ipblockCounts.f
oreachRDD,一个 rdd 里面。调用 rdd.collectAsMap 将 rdd 转化为 map。数据类型为 collection.Map,复制到声明的 map,有了数据类型由 ipblockCountsMap 接收=rdd.collectAsMap。报红,将 val 改为 var。
定义了 map,接收了 rdd 转化的 map。计算通过 IP 截取时 map key 是 String,String 为 IP,Int 是值,拿到 IP get 即可。最终数据转换为 map 以便后期提取使用。
//将最终数据转换为 Map,便于后续提取使用。
var ipBlockCountsMap :collection.Map[string,Int] =null
ipBlockCounts.foreachRDD(rdd=>{
ipBlockCountsMap=rdd.collectAsMap()
})
二、执行效果
map 输出
ipBlockCounts.foreachRDD(rdd=>rdd.foreach(println)
打出了 ipBlock 数据,哪个 IP 段,IP 段数据是多少。
执行,数据预处理程序跑起来、爬虫数据跑起来,会输出 IP 段和数字。
19/05/17 16:37:14 INFO VerifiableProperties: Property zookeeper.
connect is overridden to
19/05/17 16:37:14 INFO VerifiableProperties: Property zookeeper.
connect is overridden to
(192.168.6)
IP 段和数量出现,第一个指标统计 IP 段访问量统计完毕,IP 段没问题,窗口的宽度是6秒钟,要计算的是6秒钟之间的数据,每两秒钟跑一次,爬虫是1秒钟跑一次,窗口为6秒钟,1秒钟跑6次,结果6没问题。IP 段,6正确。
第一个指标5分钟内 IP 段访问量做完,代码写完,效果看到,数据正确