Spark- 根据IP获取城市(java)
开源 IP 地址定位库 ip2region 1.4
ip2region 是准确率 99.9% 的 IP 地址定位库,0.0x毫秒级查询,数据库文件大小只有 2.7M,提供了 Java、PHP、C、Python、Node.js、Golang 的查询绑定和 Binary、B树、内存三种查询算法,妈妈再也不同担心我的 IP 地址定位!
ip2region 1.4 更新如下:
-
数据升级至 2018/01/12 的版本,包括 ip.merge.txt 和 ip2region.db。
-
升级的数据增加了 ipip 的缺失验证,主数据源缺失的数据使用 ipip 补充。
升级提醒:因为每次更新都有可能会更改 ip2region.db 的生成配置,请保持使用最新版本的 binding。
下载地址:
码云:https://gitee.com/lionsoul/ip2region/tree/v1.4-release
github:https://github.com/lionsoul2014/ip2region/releases/tag/v1.4-release
一.Java - 使用Ip2Region(ip地址定位库)转换IP和地区
创建Maven工程(略)
如果使用IDEA,可先创建普通工程,然后右键点击工程,执行“Add Frameowrk support”,选择Maven,即可快速转换为Maven工程。
引入Maven依赖
<dependencies> <dependency> <groupId>org.lionsoul</groupId> <artifactId>ip2region</artifactId> <version>1.4</version> </dependency> </dependencies>
1 import org.lionsoul.ip2region.*; 2 3 /** 4 * Ip2Region测试类 5 * @author Zebe 6 */ 7 public class Ip2RegionTest { 8 9 /** 10 * 程序入口 11 * @param args 运行参数 12 */ 13 public static void main(String[] args) throws Exception { 14 String ip = "47.95.196.158"; 15 // 判断是否为IP地址 16 boolean isIpAddress = Util.isIpAddress("12123.34"); // false 17 isIpAddress = Util.isIpAddress(ip); // true 18 19 // IP地址与long互转 20 long ipLong = Util.ip2long(ip); // 794805406 21 String strIp = Util.long2ip(ipLong); // 47.95.196.158 22 23 // 根据IP搜索地址信息 24 DbConfig config = new DbConfig(); 25 String dbfile = "D:\\data\\ip2region.db"; // 这个文件若没有请到以下地址下载: 26 // https://gitee.com/lionsoul/ip2region/tree/master/data 27 DbSearcher searcher = new DbSearcher(config, dbfile); 28 29 // 二分搜索 30 long start = System.currentTimeMillis(); 31 DataBlock block1 = searcher.binarySearch(ip); 32 long end = System.currentTimeMillis(); 33 System.out.println(block1.getRegion()); // 中国|华东|浙江省|杭州市|阿里巴巴 34 System.out.println("使用二分搜索,耗时:" + (end - start) + " ms"); // 1ms 35 36 // B树搜索(更快) 37 start = System.currentTimeMillis(); 38 DataBlock block2 = searcher.btreeSearch(ip); 39 end = System.currentTimeMillis(); 40 System.out.println("使用B树搜索,耗时:" + (end - start) + " ms"); // 0ms 41 } 42 }
其中需要下载ip2region.db:
二.使用Ip2Region(ip地址定位库)转换IP和地区
1 public static void DownLoadDbFile(String path) { 2 3 FileSystem fs,local; 4 try { 5 fs = FileSystem.get(new URI(path.substring(0, path.indexOf('/', path.indexOf(':') + 3))), new Configuration()); 6 local = FileSystem.getLocal(new Configuration()); 7 local.delete(new Path("/tmp/ip2region.db"), true); 8 fs.copyToLocalFile(false, new Path(path), new Path("/tmp/ip2region.db")); 9 } catch (IOException e) { 10 // TODO 自动生成的 catch 块 11 SparkLog.error(e); 12 } catch (URISyntaxException e) { 13 // TODO 自动生成的 catch 块 14 SparkLog.error(e); 15 } 16 } 17 18 19 public static void Ip2RegionTest() { 20 FileSystem fs,local; 21 String path="hdfs://10.8.18.74:8020/user/lyy/data/ip2region.db";//先将db文件上传到环境中的hdfs上 22 try { 23 fs = FileSystem.get(new URI(path.substring(0, path.indexOf('/', path.indexOf(':') + 3))), new Configuration()); 24 local = FileSystem.getLocal(new Configuration()); 25 local.delete(new Path("/tmp/ip2region.db"), true); 26 fs.copyToLocalFile(false, new Path(path), new Path("/tmp/ip2region.db"));//下载db文件到相应的driver和excutor节点本地的/tmp的目录下 27 } catch (Throwable e) { 28 // TODO 自动生成的 catch 块 29 e.printStackTrace(); 30 } 31 32 String ip =""; 33 34 DbConfig config; 35 try { 36 JavaSparkContext sc = SparkCommon.getJavaSparkContext(); 37 38 JavaRDD<String> rdd = sc.parallelize(Arrays.asList("91.235.133.117","62.87.232.88")); 39 40 config = new DbConfig(); 41 DbSearcher searcher = new DbSearcher(config, "/tmp/ip2region.db"); 42 SparkLog.info(rdd.count()); 43 //以下的迭代及转化都在driver端完成,这里存在风险,当数据量超大的时候,driver可能出现OOM 44 Iterator<String> It = rdd.collect().iterator(); 45 while(It.hasNext()){ 46 ip = It.next(); 47 DataBlock block2 = searcher.btreeSearch(ip); 48 SparkLog.info(block2.getRegion()); 49 } 50 51 } catch (Throwable e) { 52 // TODO 自动生成的 catch 块 53 e.printStackTrace(); 54 } 55 /*这里展示的转换后的ip和region的信息如何再次组织成rdd,并转换成dataset的一种方法 56 List<Row> lst = new ArrayList<>(); 57 while(It.hasNext()){ 58 ip = It.next(); 59 DataBlock block2 = searcher.btreeSearch(ip); 60 lst.add(RowFactory.create(ip,block2.getRegion())); 61 } 62 SparkSession session = SparkCommon.getSparkSessionInstance(); 63 64 StructType schema = new StructType(new StructField[]{ 65 new StructField("hostname1", DataTypes.StringType, false, Metadata.empty()), 66 new StructField("country", DataTypes.StringType, false, Metadata.empty()), 67 }); 68 69 Dataset<Row> ip2region = session.createDataFrame(SparkCommon.getJavaSparkContext().parallelize(lst), schema); 70 71 return df.join(ip2region,df.col("hostname").equalTo(ip2region.col("hostname1")));*/ 72 73 }