该项目主要实现的主要功能:
一是通过探针设备采集可监测范围内的手机MAC地址、与探针距离、时间、地理位置等信息:
二是探针采集的数据可以定时发送到服务端保存:
三是利用大数据技术对数据进行人流量等指标的分析。最终以合理的方式展示数据处理结果。
数据收集
数据收集由服务器和探针设备共同完成,探针采集数据并发送到服务器,服务器接收探针设备的数据,处理成定格式保存至分
布式文件系统(HDFS)中,供数据处理使用。 下面介绍探针采集数据的原理。
术语介绍:
STA: (station) 工作站,指手机或者电脑等连接WiFi的设备。
AP: (AcessPoint)接入点,指无线路由器等产生WiFi热点的设备。
SSID: ( Service Set dentifer)服务集标识,就是WiFi的名字。
在无线领域中STA总是不断试图寻找周边存在的AP,所以我们可以利用这种特性来发现一个未连接 AP的STA,而对于一个已经
连接到AP的STA,也可以通过截狭它发出的数据帧来获取MAC、与探针之间的距离和它当前连接的SSID等信息。
数据清洗:
探针上传的数据是一种半结构化数据,如:真实的数据很大
id:嗅探设备ID
mmac:嗅探器设备自身Wifi MAC
rate:发送频率
wssid:嗅探器设备连接的WiFi的MAC地址
time:时间戳,采集这些MAC的时间
lat:纬度 lon:经度
addr:地址
mac:采集到的手机的MAC地址
rssi:手机的信号强度
range:手机距离嗅探设备的距离
ts:目标ssid,手机连接的WiFi的ssid
tmc:手机连接的WiFi的地址
tc:是否与路由器连接
ds:手机是否睡眠
essidn:曾今连接的WiFi的SSID
该数据属于半结构化数据,其中包含探针设备ID,设备自身WFIMAC,发送频率,设备连接的WFi的SID设备连接的WFI的
MAC地址、时间戳,采集到这些MAC的时间、纬度、经度、地址信息,以及一组被探测到的设备信息, 设备信息包括
手机的MAC、信号强度、与探针之间的距离、手机连接WiFi的SID手机连接的WFI的MAC地址、手机曾经连接过的WiFi的
SSID需要在清洗过程中去除所有无用的数据,使之变成结构化的文件,到这里数据清洗的第一步就完成了。
第二步使用Spark SQL完成,在这一一步中完成时间点到时间段的转化,即在处理之前每一条记录表示一个终端在某 一时间
点的状态,而在结果中一条记录表示一 个终端在一段时间内的状态。
经过数据清洗,不仅大大减小了数据集的容量,也为后续的数据处理提供了极大的方便。
客流数据分析
我们将得到以下指标:
客流量:店铺或区域整体客流及趋势。
入店量:进入店铺或区域的客流及趋势。
入店率:进入店铺或区域的客流占全部客流的比例及趋势。来访周期:进入店铺或区域的顾客距离上次来店的间隔。
新老顾客:一定时间段内首次/两次以上进入店铺的顾客。
顾客活跃度:按顾客距离上次来访间隔划分为不同活跃度(高活跃度、中活跃度、低活跃度、沉睡活跃度) .
驻店时长:进店铺的顾客在店内的停留时长,
跳出率:进店铺后很快离店的顾客及占比(占总体客流) .
深访率:进店铺深度访问的顾客及占比(占总体客流,可以根据定位轨迹或者停留时长判定).
数据导出
系统分析结果直接保存为文本文件,保存在HDFS中。
分析结果最终会被导入关系型数据库,供后续生成图表使用,该展示系统使用PHP做后台,前端使用HTML和JS生成图表。
功能设计:
HDFS中是原始数据集(data表(主要字段:tanzhen_id mac(不同的mac代表不同客户)time range),通过Spark SQL
得到)----------->visit表(取出同一mac所有数据,按照time遍历,得到每一个用户的每一次访问记录),
visit表主要字段(MAC start_time leave_time stay_time)
思路:data表首先抽取每一个用户(MAC)的数据,对每个用户数据进行遍历,得到每个用户每一次的访问记录。
通过visit表得到:客流量、入店率,来访周期,新老顾客,顾客活跃度等等。
指标说明
(1)店铺外人流走势/客流量/入店量/入店率/离店量
店铺外人流/客流量,在实时接收探针数据过程中根据range字段(范围)以及数据条数实时得到。
入店量/离店量是对visit表分别按start_time、 leave_time字段从小到大遍历统计规定时间段内的记录条数。
(2)跳出率/深访率/驻店时长
对visit 表按time字段从小到大遍历统计规定时间段内记录条数stay_time小于三分钟和大于20分钟的记录条数以及
stay_time均值。
(3)新老顾客数/顺客活跃度
对visit表按time字段排序,按一定定时间段遍历,新顾客收等于该时间段结束时刻之前所有的顺客数减去该时间段开始时刻
之前所有的顾客数,老顾客数等于该时间段内顾客数减去新顾客数。
数据库结构
项目的数据处理过程,处理过程中的每个少 驿都至少依赖张表,本节将介绍项目用到的数据库结构,包括表名和每张表包舍的
字设名,原始数据表是数据接收服务器最终存储到HDFS中的数据,中向结果表是经过第2次收据清洗后的输出结果,数据表
说明如下。
原始数据data 表主要字段:
tanzhen_id:探针设备的id,
mac:用户设备的MAC.
time:探测到当前设备的时间,
range:该设备与探什之间的距离。
中间结果vistor表主要字段1
mac:标识不同用户.
start_time:用户入店时间,
leave_time:用户离店时间。
stay_time;用户停留时间。
上传数据到HDFS:
因为是用python等语言处理过的,所以传的数据格式为:只提取有用的数据:
数据清洗代码:命令行可以用来调试看数据结构
timeArray有四个time是因为时间格式划分为四块。
完整源码:
package com.victor.spark.WiFiData
/**
* Company: Huazhong University of science and technology
* 华中科技大学电气学院聚变与等离子体研究所
* Version: V1.0
* Author: Victor
* Contact: [email protected] 2018--2020
* Software: IntelliJ IDEA
* File: wifi
* Time: 2018/11/11 17:12
* Desc:
**/
package com.victor.spark.WifiProject
import org.apache.spark.sql.SparkSession
import scala.util.control.Breaks
object new_customer_extract {
def main(args: Array[String]): Unit = {
val spark = SparkSession.builder().appName("customer_extract")
.config("spark.some.config.option","some-values")
.getOrCreate()
import java.io._
val writer = new PrintWriter(new File("/spark/data/re.txt"))//for the storage of result
import spark.implicits._
//read the data
val df = spark.read.json("/spark/data/log.json")
//create the view data for df
df.createOrReplaceTempView("data")
spark.sql("cache table data")
//get all MAC of all users
val macArray = spark.sql("SELECT DISTINCT mac FROM data").collect()
var i =0
val inner = new Breaks
val lenth = macArray.length
//loop for each user
while(i<lenth){
var resultString = ""
var mac = macArray(i)(0)
val sql = "SELECT 'time' from data where mac='"+mac+"'order by 'time'"
val timeArray = spark.sql(sql).collect()
//to get timeList from timeArray
import scala.collection.mutable.ListBuffer
var timeList = new ListBuffer[Int]
var list_length = timeArray.length
var j = 0
while (j < list_length){
timeList += timeArray(i)(0).toString.toInt
j = j+1
}
var k = 0
var oldTime = 0
var newTime = 0
var maxVisitTimeInterval = 300
var startTime = 0
var leaveTime = 0
while (k < list_length){
if(k == 0){
oldTime = timeList(0)
newTime = timeList(0)
startTime = timeList(0)
}
else if(k == (list_length - 1)){
leaveTime = timeList(k)
var stayTime = leaveTime - startTime
resultString += """{"mac":"""" + mac + """,""" +""""in_time":"""+startTime+","+""""out_time":"""
+leaveTime+","+""""stay_Time":"""+stayTime+"}\n"
}else{
newTime = timeList(k)
if ((newTime - oldTime) > maxVisitTimeInterval){
leaveTime = oldTime
var stayTime = leaveTime-startTime
resultString += """{"mac":"""" + mac + """,""" +""""in_time":"""+startTime+","+""""out_time":"""
+leaveTime+","+""""stay_Time":"""+stayTime+"}\n"
startTime = newTime
oldTime = newTime
}else{
oldTime = newTime
}
}
k = k +1
}
writer.write(resultString)
i = i+1
}
writer.close()
spark.sql("uncache table data")
}
}
数据处理流程
在面我们完成了数据的初步处理,接下来我们将使用这些几余较小的数据计算以下指标:
客流量:店铺或区域整体客流及趋势。
入店量:进入店铺或区域的客流及趋势。
入店率:通俗一点讲就是在单位时间内,从店铺门口经过的客流量与进入店铺内的客流量的比率。
来访周期:进入店铺或区域的顾客距离上次来店的问隔。
新老顾客:一定时间段内首次/两次以上进入店铺的顾客。
顾客活跃度:按顾客距离上次来访间隔,划分为不同活跃度(高活跃度、中活跃度、低活跃度、沉睡活跃度)。
驻店时长:进入店铺的顾客在店内的停留时长。
跳出率:进入店铺后很快离店的顾客及占比(占总体客流)。
深访率:进入店铺深度访问的顾客及占比(占总体客流).
源码更新中。。。。。。。。。。