开发者学堂课程【大数据实战项目:反爬虫系统(Lua+Spark+Redis+Hadoop 框架搭建)第三阶段):数据预处理-数据解析-确定解析规则思路及效果】学习笔记,与课程紧密联系,让用户快速学习知识。
课程地址:https://developer.aliyun.com/learning/course/671/detail/11662
数据预处理-数据解析-确定解析规则思路及效果
内容介绍:
一、代码实现
二、代码执行
一、代码实现
前面完成了规则的读取,并加载到了广播变量里,解析的代码也完成了如下:
val queryRequestData =
AnalyzeRequest.analyzeQueryRequest( requestType,
requestMethod,contentType,requestUrl,requestBody,travel
Type, broadcastQueryRules.value)
这一行代码就能把规则解析出来,它是怎么解析的?
这里定义了一个方法,叫 queryRequestDate,这里面调用了一个叫 analyzeRequest,然后这里面有一个叫 analyQueryRequest。它后面括号里传了这么几个参数,先来看一下参数 requestType ,它是前面解析好的是飞行类型还是操作类型的标签。后面这个是 requestMethod 和 contentType ,还有 requesturl 都在前面做的数据拆分里面。
//数据拆分功能
val(requesturl ,requestNethod ,contentType ,requestBotdy,
httpReferrer ,remoteAddr ,httpUserAgent ,timeIso8601,
serverAddr ,cookiesstr ,cookievalue_JESSIONID,
cookievalue_usERID) =Datasplit.datasplit(encryptedId)
上面的代码就包含了之前需要的所有参数,所以做数据拆分,就是因为后续的计算会反复的用到这些数据。如果每次用它的时候再来拆分,就会很麻烦。所以做数据拆分就是一劳永逸了。
Traveltype 是刚刚计算出的单程和往返的标签。然后还有广播变量 broadcastQueryRules,因为这里面解析的是查询类的数据,广播变量的读取规则代码是:
//将规则加载到广播变量
@volatile var broadcastQueriyRules=sc.broadcast(queryRule)
因为这里面也是查询类的数据,也就是说把查询类的这三个规则,也就是把 behavior_type 等于零的读过来。读过来以后就是参数。广播变量放到这个方法里。那么这个方法是什么意思?
先看 analyzeRequest。这个就是解析数据的代码,它是已经写好的。
数据解析方法里面需要的几个参数也是前面算好的,因为解析数据要用到这几个参数,所以直接把参数传到这个方法里就行。
这里面有一个 analyzeQueryRequest ,也就是下图的这个方法:
它是来解析查询类的数据的,不同类型的数据根据不同的解析规则来进行解析。
怎么解析?刚刚读过来的规则是查询类的,而现在里面有三种情况,所以查询类的 query 也有三种情况。
目的是解析这个数据,那现在有三种选择,只能用一个。
所以下面的代码告诉了方法:
val queryRequestData: QueryRequestData = new
QueryRequestData
//数据库中有四条解析规则,我们需要通过传过来的这一条数据,确定数据凡配上的解析规则,然后用这个解析规则解析数据
val matchedRules = analyzeRules.filter { rule =>
//先根据请求方式和请求类型过滤出是属于查询的规则
if (rule.requestMethod .equalsIgnoreCase(requestMethod)
&& rule.BehaviorType ==requestTypelabel.behaviorType.id)
true
else
false
}
看里面的 analyzeRules ,就是最后一个参数。
这里有一个 filter ,用filter 去过滤,现在有三个规则,那么最起码要过滤两个。
这里有一个 analyzeRules.fliter 它是在数据库里查出来的,在数据库当中有一个 request method ,是三个数据库中的第一个指标的。判断代码是:
rule.requestMethod .equalsIgnoreCase(requestMethod)
看下图:
这个是判断是否相等的。用之前计算的 requestMethod 跟数据库里面配置出来的 requestMethod 比较。因为计算的数据都是 post 那让它和数据库里面的 post 比较,不等于的就返回 false 然后过滤掉。所以现在是有三种选择,这里面通过的 requestMethod 都是 post 。而数据库的第三个规则,也就是图中第四行是 get ,那么它就要被过滤掉。这样就从三个选择变成了两个选择。
看下一个,Rule.behaviorType 也就是这里面的 behavior_type。
这个标记的 Requesttypelabel ,就是前面计算的 Requesttype。
也就是说,数据库当中的 behaviorType 等于数据计算出来的behaviorType的id。
数据库里面的 behaviorType 是0,而现在的数据已经确定都是国内查询,也就是behaviorType是查询型的,那么这里面拿到的一定是0。所以两个都是0,也就没有过滤掉数据,所以到目前为止还是两个数据,如果这两个条件都满足,就返回 true ,不然就返回 false。
下面就是上述方法的代码:
if(rule.requestMethod.equalsIgnoreCase(requestMethod&&
rule.Behavior==requestTypeLabel.behaviorType.id)
true
else
false
还剩下两条数据,这时就要用到 filter 。调用 request,也就是之前解析的requesturl。
代码如下:
.filter { rule =>
//然后根据url正则表达式,过滤出是属于国内查询还是国际查询 request.matches(rule.requestMatchExpression)
requestMatchExpression 这个字段就在数据库当中。
如下图所示:
它是正则表达式。那用数据传过来的解析出来的 url 去匹配它的规则,如果匹配上就是 true,没匹配上就是 false 。
这里面有一个 app 有一个 query.ao,而数据过滤完以后,
val DataProcess= filteredData.map( message=>{
过滤后的数据都是 query.ao ,所以这个 query.ao 能匹配上返回 true ,app 就无法匹配返回 false 。经过这个操作,从两个选择,就成功的从两个选择里面。从这两个选择里面变成了只有一个选择。这样就明确到底该用哪一个规则来解析数据。此刻就用 depcity, arrcity,flightdate 来解析。
后面的代码就是来实现数据的解析的。按照这一批数据的规则来解析,解析完了以后出发地、目的地和起飞时间就都有了。后面的代码就是解析的过程,但是太多这里就不进行展示。
二、代码执行
解析完以后来看一下实际的效果。
//3对数据进行解析(在多种解析规则的情况下,确定最终使用哪一个规则进行解析)
val queryRequestData =
AnalyzeRequest.analyzeQueryRequest(requestType,
requestMethod,contentType,requesturl,requestBody,
travelType, broadcastQueryRules.value)
这个解析完以后接收回来的数据。把这个数据输出一下。
val queryRequestData = AnalyzeRequest .
analyzequeryRequest(requestType,requestMethod,contentType,requesturl,requestBody,travelType,
broadcastQueryRules.value)
val data= queryRequestData match {
case Some(datas)=> datas.depcity}
data
先随便先给个数据,做一个输出。这里返回出发地打出来。打出来以后,在前面做一个接收(val data =),然后对 data 进行一个返回。
执行这个代码看一下是不是能够把出发地解析出来。
然后把爬虫跑起来,看一下效果。
.add(new BasicNamevaluePair(
name:"json",
value: "{(\ "depcity \" : \ CAN\",\"arrcity\" : “WUH\",\“flightdate\":\"2018220\",\"adultnum)":\"1\",
这样如果解析结果正确,就会输出 CAN,看下面的结果:
爬虫的 depCity 是 CAN,这样就说明解析正确。
再来把出发地改成起飞日期:
case Some(datas)=> datas.flightDate}
日期是20180220,
然后再次执行,看下面结果:
所以起飞日期就被解析出来了。这样就把解析的工作做完了。
所以 case Some(datas)=> datas 中的数据想要哪个都可以拿到
解析数据就解析完成了,把程序和爬虫停掉。