文档章节

hive UDF 分享 通过IP地址获取 IDC/省份/城市

王二铁
 王二铁
发布于 2014/05/12 23:25
字数 788
阅读 2551
收藏 5

简述:

    简单的2分查找算法,根据IP地址定位IP所属的IP段,然后获取IP段的IDC/省份/城市的信息。

输入:IP地理信息文件,一般地址库拿到后需要格式化一下,参考:
  1. 如果省份是null 或者 '' ,city是null或者'' =》 省份=其他 and 城市=其他
  2. 省份非空且为直辖市,但是城市非直辖市  = 》 城市=直辖市
  3. 省份非空且非直辖市,但是城市为空 =》城市=其他
  4. 省份或城市中有(、\等非法信息 = 》 省份=其他 and 城市=其他

/user/hadoop/IP.csv

    格式:

 编号,开始IP(long),结束IP(long),省份,城市,IDC,开始IP,结束IP
    29990,16777472,16778239,福建省,其他,电信,1.0.1.0,1.0.3.255
    29991,16779264,16781311,广东省,其他,电信,1.0.8.0,1.0.15.255
    29992,16785408,16793599,广东省,其他,电信,1.0.32.0,1.0.63.255

用法 & 输出:

    编辑打包或者编译到hive中参考这篇,这里不在多说:http://my.oschina.net/wangjiankui/blog/64230

    get_ip_location_new(visitip,'IDC')   //返回IDC信息

    get_ip_location_new(visitip,'REGION')  //返回省份信息

    get_ip_location_new(visitip,'CITY')   //返回城市信息


代码:

package com.xxx.hive.udf;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.URI;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.StringTokenizer;
import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.fs.FSDataInputStream;
import org.apache.hadoop.fs.FileSystem;
import org.apache.hadoop.fs.Path;
import org.apache.hadoop.hive.ql.exec.UDF;
import org.apache.hadoop.io.IOUtils;
import org.apache.hadoop.io.Text;

public class UDFGetIPLocationNew extends UDF
{
  public static List<String> map = new ArrayList();
  public static long[] start_from_index;
  public static long[] end_to_index;
  public static Map<Long, String> idcCache = new HashMap();
  public static Map<Long, String> regionCache = new HashMap();
  public static Map<Long, String> cityCache = new HashMap();

  private void LoadIPLocation()
  {
    Configuration conf = new Configuration();
    String namenode = conf.get("fs.default.name");
    String uri = namenode + "/user/hadoop/IP.csv";
    FileSystem fs = null;
    FSDataInputStream in = null;
    BufferedReader d = null;
    try
    {
      fs = FileSystem.get(URI.create(uri), conf);
      in = fs.open(new Path(uri));
      d = new BufferedReader(new InputStreamReader(in));
      String s = null;
      while (true)
      {
        s = d.readLine();
        if (s == null) {
          break;
        }
        map.add(s);
      }
    }
    catch (IOException e) {
      e.printStackTrace();
    } finally {
      IOUtils.closeStream(in);
    }
  }

  public static int binarySearch(long[] start, long[] end, long ip)
  {
    int low = 0;
    int high = start.length - 1;
    while (low <= high) {
      int middle = (low + high) / 2;
      if ((ip >= start[middle]) && (ip <= end[middle]))
        return middle;
      if (ip < start[middle])
        high = middle - 1;
      else {
        low = middle + 1;
      }
    }
    return -1;
  }

  public static long ip2long(String ip)
  {
    if (ip.matches("\\d{1,3}\\.\\d{1,3}\\.\\d{1,3}\\.\\d{1,3}")) {
      String[] ips = ip.split("[.]");
      long ipNum = 0L;
      if (ips == null) {
        return 0L;
      }
      for (int i = 0; i < ips.length; i++) {
        ipNum = ipNum << 8 | Long.parseLong(ips[i]);
      }

      return ipNum;
    }
    return 0L;
  }

  public String evaluate(Text ip, Text which) {
    long ipLong = ip2long(ip.toString());
    String whichString = which.toString();

    if ((!whichString.equals("IDC")) && (!whichString.equals("REGION")) && (!whichString.equals("CITY")))
    {
      return "Unknown Args!use(IDC or REGION or CITY)";
    }

    if (map.size() == 0) {
      LoadIPLocation();
      start_from_index = new long[map.size()];
      end_to_index = new long[map.size()];
      for (int i = 0; i < map.size(); i++) {
        StringTokenizer token = new StringTokenizer((String)map.get(i), ",");
        token.nextToken();
        start_from_index[i] = Long.parseLong(token.nextToken());
        end_to_index[i] = Long.parseLong(token.nextToken());
      }

    }

    int ipindex = 0;
    if (((whichString.equals("IDC")) && (!idcCache.containsKey(Long.valueOf(ipLong)))) || ((whichString.equals("REGION")) && (!regionCache.containsKey(Long.valueOf(ipLong)))) || ((whichString.equals("CITY")) && (!cityCache.containsKey(Long.valueOf(ipLong)))))
    {
      ipindex = binarySearch(start_from_index, end_to_index, ipLong);
    }
    if (ipindex == 0) {
      if (whichString.equals("IDC"))
        return (String)idcCache.get(Long.valueOf(ipLong));
      if (whichString.equals("REGION"))
        return (String)regionCache.get(Long.valueOf(ipLong));
      if (whichString.equals("CITY")) {
        return (String)cityCache.get(Long.valueOf(ipLong));
      }
      return "Error";
    }
    if (ipindex == -1) {
      return "Other IDC";
    }

    String[] location = ((String)map.get(ipindex)).split(",");
    if (whichString.equals("IDC")) {
      idcCache.put(Long.valueOf(ipLong), location[5]);
      return location[5];
    }if (whichString.equals("REGION")) {
      regionCache.put(Long.valueOf(ipLong), location[3]);
      return location[3];
    }if (whichString.equals("CITY")) {
      cityCache.put(Long.valueOf(ipLong), location[4]);
      return location[4];
    }
    return "Error";
  }

  public static void main(String[] args)
  {
    long startTime = System.currentTimeMillis();
    System.out.println("now:" + startTime);
    UDFGetIPLocationNew getIPLocation = new UDFGetIPLocationNew();
    Text ip = new Text("112.122.64.0");

    System.out.printf("ip = %s, %s, %s, %s\n", new Object[] { ip, getIPLocation.evaluate(ip, new Text("IDC")), getIPLocation.evaluate(ip, new Text("REGION")), getIPLocation.evaluate(ip, new Text("CITY")) });

    long endTime = System.currentTimeMillis();
    System.out.println("over:" + endTime);
    System.out.println("count:" + (endTime - startTime) * 1.0D / 1000.0D);
  }
}



#2015-06-02
补充说明:
程序中逻辑有些不严谨,照抄请慎重,最后自己梳理下逻辑修改下

© 著作权归作者所有

下一篇: hive 常用小技巧
王二铁

王二铁

粉丝 89
博文 62
码字总数 41123
作品 0
北京
后端工程师
私信 提问
加载中

评论(6)

王二铁
王二铁 博主

引用来自“Janvn”的评论

博主ip纯真库格式与IP.csv格式一样的吗?我这有一份qqwry_;ite.dat文件,但不知道怎么用,求助27
不一样,纯真库是另一篇文章用的,就是开放源码那个
J
Janvn
博主ip纯真库格式与IP.csv格式一样的吗?我这有一份qqwry_;ite.dat文件,但不知道怎么用,求助27
王二铁
王二铁 博主

引用来自“KinsomC”的评论

如果遇到192.168.*.*的局域网IP地址,怎么处理?
局域网没有地址,丢弃或者标注成局域网吧
KinsomC
KinsomC
如果遇到192.168.*.*的局域网IP地址,怎么处理?
王二铁
王二铁 博主

引用来自“xlows”的评论

感谢分析,不知道你的/IP.csv 是从哪里来的,能否分享一下呢
那个文件是公司从国外买的,具体地址忘了,分享不太好,你可以用qq的ip纯真库试试
x
xlows
感谢分析,不知道你的/IP.csv 是从哪里来的,能否分享一下呢
DataLakeAnalytics: 解析IP地址对应的国家城市地址的能力

Data Lake Analytics 作为云上数据处理的枢纽,最近加入了通过IP地址查找对应的国家、省份、城市、ISP的函数, 今天带大家体验一下。 函数详细介绍 本次一共添加了下面这些函数: : 功能最全的...

阿里云云栖社区
02/21
35
0
DataLakeAnalytics: 解析IP地址对应的国家城市的函数 - 知乎

Data Lake Analytics 作为云上数据处理的枢纽,最近加入了通过IP地址查找对应的国家、省份、城市、ISP的函数, 今天带大家体验一下。 函数详细介绍 本次一共添加了下面这些函数: : 功能最全的...

Data Lake Analytics
04/30
0
0
精准营销:挖掘日志中的手机号码信息

精准营销:挖掘日志中的手机号码信息 日志中手机号码的价值 当我们在做营销活动时,常常有这样的苦恼: 花了一大笔钱,哪些客户打开了广告,哪些客户转化成了付费用户,要有一个kpi指标来衡量...

云雷
2018/12/14
0
0
也说Hadoop敏感信息加密方案的尝试(下)

前面讲到了AES对称加密的两个不同方案,一是Hive表存储秘钥,一是用KMS来存储秘钥。在这两个大的分类下,又各自有两种不同的方案,每种方案的尝试都是因为踩到了坑,所以才不得不换一种姿势。...

问津已非少年
2016/12/18
286
0
支持脚本的 Hive 自定义函数

我们知道 Hive 目前允许我们通过 Java 定义 UDF (自定义函数), 但是需求是多样的, 固定的 UDF 往往都是不够用的, 而增加一个新的 UDF 的流程也是比较繁琐的, 尤其是通过 HiveServer 查询的时...

zqq90
2017/10/29
311
2

没有更多内容

加载失败,请刷新页面

加载更多

Experts say the weaker pound is drawing investors to the UK tech sector

UK tech companies secured a record £5.5bn in foreign investment in the first seven months of this year, research shows. This was more than the amount invested per capita in th......

wowloop
28分钟前
5
0
Add support for Android 9-patch images in BorderImage

The 9-patch image implementation in Qt Quick Controls 1 is an internal implementation detail of the Android style. It cannot handle .9.png image files out of the box, but takes ......

shzwork
33分钟前
4
0
c/c++日期时间处理函数小结

日期时间处理函数: 日期时间转为字符串 strftime/std::put_time 字符串解析成日期时间 strptime/std::get_time 时间结构转换:time_t->tm localtime:time_t->tm 时间结构转换:tm->time_t ...

chuqq
37分钟前
5
0
Apache Flink 进阶入门(二):Time 深度解析

前言 Flink 的 API 大体上可以划分为三个层次:处于最底层的 ProcessFunction、中间一层的 DataStream API 和最上层的 SQL/Table API,这三层中的每一层都非常依赖于时间属性。时间属性是流处...

大涛学长
38分钟前
4
0
创龙基于Xilinx Artix-7系列FPGA处理器

SOM-TLA7是一款由广州创龙基于Xilinx Artix-7系列FPGA自主研发的核心板,可配套广州创龙Artix-7开发板使用。核心板尺寸仅70mm*50mm,采用沉金无铅工艺的10层板设计,专业的PCB Layout保证信号...

Tronlong创龙
44分钟前
5
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部