使用Spark分析CSDN泄露的用户数据 2015-08-07 21:00

说明

CSDN泄露的用户数据的格式如下:

aaaaaaa # bbbbbb # xxxxxx@hotmail.com
aaaaaaa # bbbbbb # xxxxxx@hotmail.com
aaaaaaa # bbbbbb # xxxxxx@hotmail.com
aaaaaaa # bbbbbb # xxxxxx@hotmail.com___csdn_1
aaaaaaa # bbbbbb # xxxxxx@hotmail.com

格式为:用户名、 密码、邮箱,字段之间使用" # “(星两边各有一个空格)进行分隔。

分析最多人使用的TOPn个密码

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
var csdnRDD = sc.textFile("file:///tmp/data/csdn.txt")
csdnRDD.cache
// 映射成(name,password,email)组成的array
var tmpRDD1 = csdnRDD.map(line => line.toString().split(" # "))
// 映射成password
var tmpRDD2 = tmpRDD1.map(x => x(1))
// 映射成(password,1)
var tmpRDD3 = tmpRDD2.map(x => (x,1))
// 映射成(password,次数n)
var tmpRDD4 = tmpRDD3.reduceByKey((x,y) => x + y)
// 按次数n倒序排序
var tmpRDD5 = tmpRDD4.sortBy(x => x._2, false)
// 前RDD的前50个elements出来
tmpRDD5.take(50)
// tmpRDD5.take(50).foreach(println)

统计使用纯数字作为密码的人数

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
var csdnRDD = sc.textFile("file:///tmp/data/csdn.txt")
csdnRDD.cache
// 映射成(name,password,email)组成的array
var tmpRDD1 = csdnRDD.map(line => line.toString().split(" # "))
// 映射成password
var tmpRDD2 = tmpRDD1.map(x => x(1))
// 过滤只剩纯数字的password
var tmpRDD3 = tmpRDD2.filter(_.matches("\\d+"))
// 打印出总人数
println(tmpRDD3.count)
// 前RDD的前50个elements出来
tmpRDD3.take(10).foreach(println)
tmpRDD3.saveAsTextFile("file:///tmp/data/result_all_digit")

统计使用纯字母作为密码的人数

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
var csdnRDD = sc.textFile("file:///opt/bigdata/csdn/www.csdn.net.sql")
csdnRDD.cache
// 映射成(name,password,email)组成的array
var tmpRDD1 = csdnRDD.map(line => line.toString().split(" # "))
// 映射成password
var tmpRDD2 = tmpRDD1.map(x => x(1))
// 过滤只剩纯数字的password
var tmpRDD3 = tmpRDD2.filter(_.matches("[a-zA-Z]+"))
// 打印出总人数
println(tmpRDD3.count)
// 前RDD的前50个elements出来
tmpRDD3.take(10).foreach(println)
tmpRDD3.saveAsTextFile("file:///tmp/data/result_all_letter")

统计使用人数最多的Email服务商

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
var csdnRDD = sc.textFile("file:///opt/bigdata/csdn/www.csdn.net.sql")
// 部分记录尾部中包含"___csdn_1",需要删除掉
var tmpRDD1 = csdnRDD.map(x => x.split("___csdn_1$")(0))
// 映射成(name,password,email)组成的array
var tmpRDD2 = tmpRDD1.map(line => line.toString().split(" # "))
// 映射成邮箱
var tmpRDD3 = tmpRDD2.map(x => x(2))
// 使用正则表达式匹配email,过滤掉非法的邮箱
var tmpRDD4 = tmpRDD3.filter(_.matches("\\w+([-+.]\\w+)*@\\w+([-.]\\w+)*\\.\\w+([-.]\\w+)*"))
// 提取邮箱中的后缀
var tmpRDD5 = tmpRDD4.map(x => x.toString().split("@")(1))
// 邮箱后缀规整为全小写
var tmpRDD6 = tmpRDD5.map(x => x.toLowerCase)
// 映射成:邮箱后缀,1
var tmpRDD7 = tmpRDD6.map(x => (x,1))
// 按邮箱后缀reduce
var tmpRDD8 = tmpRDD7.reduceByKey((x,y) => x + y)
// 按次数n倒序排序
var tmpRDD9 = tmpRDD8.sortBy(x => x._2, false)
// 前RDD的前n个elements出来
tmpRDD9.take(10).foreach(println)
tmpRDD9.saveAsTextFile("file:///tmp/data/result_email_top")

分析用户名密码相同的用户

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
var csdnRDD = sc.textFile("file:///opt/bigdata/csdn/www.csdn.net.sql")
csdnRDD.cache
// 部分记录尾部中包含"___csdn_1",需要删除掉
var tmpRDD1 = csdnRDD.map(x => x.split("___csdn_1$")(0))
// 映射成(name,password,email)组成的array
var tmpRDD2 = tmpRDD1.map(line => line.toString().split(" # "))

// 过滤掉用户名与密码相同的记录
var tmpRDD3 = tmpRDD2.filter(arr => arr(0).equalsIgnoreCase(arr(1)))
println(tmpRDD3.count)
tmpRDD3.saveAsTextFile("file:///tmp/data/result_username_password_same")

分析简单密码的用户(长度小于8,只有数字和字母)

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
var csdnRDD = sc.textFile("file:///opt/bigdata/csdn/www.csdn.net.sql")
csdnRDD.cache
// 部分记录尾部中包含"___csdn_1",需要删除掉
var tmpRDD1 = csdnRDD.map(x => x.split("___csdn_1$")(0))
// 映射成(name,password,email)组成的array
var tmpRDD2 = tmpRDD1.map(line => line.toString().split(" # "))

// 映射成password
var tmpRDD3 = tmpRDD2.map(arr => arr(1))

// 过滤出长度小于8的password
var tmpRDD4 = tmpRDD3.filter(_.length < 8)

// 过滤过只有数字和大小写的password
var tmpRDD5 = tmpRDD4.filter(_.matches("^\\w+$"))
println(tmpRDD5.count)
tmpRDD5.saveAsTextFile("file:///tmp/data/result_password_short")

分析密码长度分布

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
var csdnRDD = sc.textFile("file:///opt/bigdata/csdn/www.csdn.net.sql")
csdnRDD.cache
// 部分记录尾部中包含"___csdn_1",需要删除掉
var tmpRDD1 = csdnRDD.map(x => x.split("___csdn_1$")(0))
// 映射成(name,password,email)组成的array
var tmpRDD2 = tmpRDD1.map(line => line.toString().split(" # "))

// 映射成password
var tmpRDD3 = tmpRDD2.map(arr => arr(1))
// 映射成:password长度,1
var tmpRDD4 = tmpRDD3.map(p => (p.length, 1))
// 按密码长度进行reduce
var tmpRDD5 = tmpRDD4.reduceByKey((x,y) => x + y)
// 按次数n倒序排序
var tmpRDD6 = tmpRDD5.sortBy(x => x._2, false)
// 前RDD的前n个elements出来
tmpRDD6.take(50).foreach(println)
tmpRDD6.saveAsTextFile("file:///tmp/data/result_password_length")

分析电话号码作为密码的记录

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
var csdnRDD = sc.textFile("file:///opt/bigdata/csdn/www.csdn.net.sql")
csdnRDD.cache
// 部分记录尾部中包含"___csdn_1",需要删除掉
var tmpRDD1 = csdnRDD.map(x => x.split("___csdn_1$")(0))
// 映射成(name,password,email)组成的array
var tmpRDD2 = tmpRDD1.map(line => line.toString().split(" # "))

// 映射成password
var tmpRDD3 = tmpRDD2.map(arr => arr(1))

// 过滤密码为手机号的记录
var tmpRDD4 = tmpRDD3.filter(_.matches("^((13[0-9])|(15[^4,\\D])|(18[0,5-9]))\\d{8}$"))
println("--------------------: " + tmpRDD4.count)
tmpRDD4.saveAsTextFile("file:///tmp/data/result_password_phone")
Tags: #Spark    Post on Spark