Spark案例之根據ip地址計算歸屬地一
阿新 • • 發佈:2018-11-10
1.需求
根據訪問日誌中的ip地址計算出訪問者的歸屬地,並且按照省份,計算出訪問次數,最後將計算好的結果寫入到Mysql中
2.思路分析
1)整理訪問日誌中的資料,切分出ip欄位,然後將ip欄位轉換成十進位制
2)載入ip地址的規則,取出有用的欄位,然後將資料快取到記憶體中(Executor中的記憶體)
3)將訪問日誌中的ip與ip地址的規則進行匹配(使用二分查詢進行匹配)
4)取出對應的省份名稱,將其和1組合在一起
5)按照省份名進行聚合
6)將聚合後的資料寫入Mysql
3.本地模式實現
有了上邊的分析,我們可以現在本地模式下實現一下,在本地模式下實現起來比較簡單
先放上實現程式碼和效果:
package cn.ysjh0014 import scala.io.{BufferedSource, Source} object TestIp { //將ip地址轉換為十進位制 def ip2Long(ip: String): Long = { val fragments = ip.split("[.]") var ipNum = 0L for (i <- 0 until fragments.length) { ipNum = fragments(i).toLong | ipNum << 8L } ipNum } //讀取ip規則,並整理 def readRules(path: String): Array[(Long, Long, String)] = { //讀取ip規則 val bf: BufferedSource = Source.fromFile(path) val lines: Iterator[String] = bf.getLines() //對ip規則進行整理,並放入到記憶體 val rules: Array[(Long, Long, String)] = lines.map(line => { val fileds = line.split("[|]") val startNum = fileds(2).toLong val endNum = fileds(3).toLong val province = fileds(7) (startNum, endNum, province) }).toArray rules } //二分查詢 def binarySearch(lines: Array[(Long, Long, String)], ip: Long): Int = { var low = 0 var high = lines.length - 1 while (low <= high) { val middle = (low + high) / 2 if ((ip >= lines(middle)._1) && (ip <= lines(middle)._2)) return middle if (ip < lines(middle)._1) high = middle - 1 else { low = middle + 1 } } -1 } def main(args: Array[String]): Unit = { //讀取ip規則,這些資料是在記憶體中 val rules: Array[(Long, Long, String)] = readRules("D:\\視訊\\小牛學堂-2018\\06-Spark安裝部署到高階-10天\\spark-04-Spark案例講解\\課件與程式碼\\ip\\ip.txt") //將ip轉換為十進位制 val ipNum = ip2Long("120.78.142.230") //查詢 val index = binarySearch(rules, ipNum) var Num = "未查詢到該ip所在地區" if (index != -1) { Num = rules(index)._3 } print(Num) } }
執行結果:
上邊測試的ip地址是我買的阿里雲的伺服器的公網ip地址,廣東省深圳市的,還算比較準確,這個ip地址的規則實在淘寶買的,比較早期的,不是很全面
日誌檔案及ip地址規則下載: 連結:https://pan.baidu.com/s/1G0DuO2pTbYCm-Ym6V0KDYw
提取碼:6egh