Tüm Ürünler
Search
Belge Merkezi

MaxCompute:MaxCompute UDF'leri ile IP adreslerini coğrafi konumlara dönüştürme

Son Güncelleme:Oct 04, 2026

Bir IP adresi veritabanını sorgulayarak IPv4 veya IPv6 adreslerini coğrafi konumlara dönüştüren bir MaxCompute kullanıcı tanımlı işlevi (UDF) oluşturabilirsiniz.

Arka plan bilgileri

IP adreslerini coğrafi konumlara dönüştürmek için bir IP adresi veritabanı gerekir. IP adresi veritabanı dosyalarını indirip kaynak olarak MaxCompute projenize yüklemelisiniz. Ardından bu kaynaklara başvuran bir MaxCompute UDF'si geliştirip kaydedebilir ve IP adreslerinin coğrafi konumlarını çözmek için SQL deyimlerinde bu işlevi çağırabilirsiniz.

Önemli

Bu konuda sunulan IP adresi veritabanı dosyaları yalnızca gösterim amaçlıdır. İş gereksinimlerinize göre kendi IP adresi veritabanınızı sürdürmeniz gerekir.

Ön koşullar

Yordam

Bir MaxCompute UDF'si kullanarak IPv4 veya IPv6 adreslerini coğrafi konumlara dönüştürmek için aşağıdaki adımları tamamlayın:

  1. Adım 1: IP adresi veritabanı dosyalarını yükleyin

    IP adresi veritabanı dosyalarını kaynak olarak MaxCompute projenize yükleyin. Oluşturacağınız MaxCompute UDF'si bu kaynaklara bağımlıdır.

  2. Adım 2: Proje bağlantısı oluşturun

    Bir MaxCompute projesine bağlanın ve bir MaxCompute Java modülü oluşturun.

  3. Adım 3: MaxCompute UDF'sini yazın

    IntelliJ IDEA'da MaxCompute UDF kodunu yazın.

  4. Adım 4: MaxCompute UDF'sini kaydedin

    MaxCompute UDF'sini kaydedin.

  5. Adım 5: IP adreslerini coğrafi konumlara dönüştürmek için MaxCompute UDF'sini çağırın

    Kayıtlı işlevi bir SQL deyimi içinde çağırarak IP adreslerini coğrafi konumlara dönüştürün.

Adım 1: IP adresi veritabanı dosyalarını yükleyin

  1. IP adresi veritabanı dosyalarını yerel makinenize indirin, paketi açarak ipv4.txt ve ipv6.txt dosyalarını çıkarın ve bunları MaxCompute istemcisinin ...\odpscmd_public\bin kurulum dizinine yerleştirin.

  2. MaxCompute istemcisini yükleyin ve oturum açın, ardından hedef MaxCompute projenize geçin.

  3. add file komutunu çalıştırarak ipv4.txt ve ipv6.txt dosyalarını dosya kaynağı olarak MaxCompute projesine yükleyin.

    ADD file ipv4.txt -f;
    ADD file ipv6.txt -f;

    Kaynak ekleme hakkında daha fazla bilgi için Kaynak ekleme konusuna bakın.

  4. (Yerel hata ayıklama için) ipv4.txt ve ipv6.txt dosyalarını yerel projenizin warehouse/example_project/_resources_ dizinine kopyalayın.

Adım 2: Proje bağlantısı oluşturun

  1. Bir MaxCompute projesine bağlanın. Daha fazla bilgi için Proje bağlantılarını yönetme konusuna bakın.

  2. Bir MaxCompute Java modülü oluşturun. Daha fazla bilgi için MaxCompute Java modülü oluşturma konusuna bakın.

Adım 3: MaxCompute UDF'sini yazın

  1. Java sınıfları oluşturun.

    Aşağıdaki adımlardaki UDF kodu bu Java sınıflarını kullanır.

    1. IntelliJ IDEA'da Project bölmesinde modül kaynak dizinine (src > main > java) sağ tıklayın ve New > Java Class seçeneklerini seçin.

    2. New Java Class iletişim kutusunda sınıf adını girin, Enter tuşuna basın ve ardından kod düzenleyicide kodu girin.

      Aşağıdaki üç Java sınıfını sırayla oluşturun. Sağlanan kodu değiştirmeden kullanabilirsiniz.

      • IpUtils

        package com.aliyun.odps.udf.utils;
        import java.math.BigInteger;
        import java.net.Inet4Address;
        import java.net.Inet6Address;
        import java.net.InetAddress;
        import java.net.UnknownHostException;
        import java.util.Arrays;
        public class IpUtils {
            /**
             * Converts an IP address from a string to a long.
             *
             * @param ipInString
             * The IP address as a string.
             * @return The IP address as a long.
             */
            public static long StringToLong(String ipInString) {
                ipInString = ipInString.replace(" ", "");
                byte[] bytes;
                if (ipInString.contains(":"))
                    bytes = ipv6ToBytes(ipInString);
                else
                    bytes = ipv4ToBytes(ipInString);
                BigInteger bigInt = new BigInteger(bytes);
        //        System.out.println(bigInt.toString());
                return bigInt.longValue();
            }
            /**
             * Converts an IP address from a string to a BigInteger string.
             *
             * @param ipInString
             * The IP address as a string.
             * @return A BigInteger representation of the IP address as a string.
             */
            public static String StringToBigIntString(String ipInString) {
                ipInString = ipInString.replace(" ", "");
                byte[] bytes;
                if (ipInString.contains(":"))
                    bytes = ipv6ToBytes(ipInString);
                else
                    bytes = ipv4ToBytes(ipInString);
                BigInteger bigInt = new BigInteger(bytes);
                return bigInt.toString();
            }
            /**
             * Converts an IP address from a BigInteger to a string.
             *
             * @param ipInBigInt
             * The IP address as a BigInteger.
             * @return The IP address as a string.
             */
            public static String BigIntToString(BigInteger ipInBigInt) {
                byte[] bytes = ipInBigInt.toByteArray();
                byte[] unsignedBytes = Arrays.copyOfRange(bytes, 1, bytes.length);
                // Remove the sign bit.
                try {
                    String ip = InetAddress.getByAddress(unsignedBytes).toString();
                    return ip.substring(ip.indexOf('/') + 1).trim();
                } catch (UnknownHostException e) {
                    throw new RuntimeException(e);
                }
            }
            /**
             * Converts an IPv6 address to a signed byte[17] array.
             */
            private static byte[] ipv6ToBytes(String ipv6) {
                byte[] ret = new byte[17];
                ret[0] = 0;
                int ib = 16;
                boolean comFlag = false;// Flag for IPv4-mapped addresses.
                if (ipv6.startsWith(":"))// Remove the leading colon.
                    ipv6 = ipv6.substring(1);
                String groups[] = ipv6.split(":");
                for (int ig = groups.length - 1; ig > -1; ig--) {// Scan in reverse.
                    if (groups[ig].contains(".")) {
                        // An IPv4-mapped address is found.
                        byte[] temp = ipv4ToBytes(groups[ig]);
                        ret[ib--] = temp[4];
                        ret[ib--] = temp[3];
                        ret[ib--] = temp[2];
                        ret[ib--] = temp[1];
                        comFlag = true;
                    } else if ("".equals(groups[ig])) {
                        // Zero-length compression is found. Calculate the number of missing groups.
                        int zlg = 9 - (groups.length + (comFlag ? 1 : 0));
                        while (zlg-- > 0) {// Set these groups to 0.
                            ret[ib--] = 0;
                            ret[ib--] = 0;
                        }
                    } else {
                        int temp = Integer.parseInt(groups[ig], 16);
                        ret[ib--] = (byte) temp;
                        ret[ib--] = (byte) (temp >> 8);
                    }
                }
                return ret;
            }
            /**
             * Converts an IPv4 address to a signed byte[5] array.
             */
            private static byte[] ipv4ToBytes(String ipv4) {
                byte[] ret = new byte[5];
                ret[0] = 0;
                // Find the positions of the dots in the IP address string.
                int position1 = ipv4.indexOf(".");
                int position2 = ipv4.indexOf(".", position1 + 1);
                int position3 = ipv4.indexOf(".", position2 + 1);
                // Convert the string segments between the dots to integers.
                ret[1] = (byte) Integer.parseInt(ipv4.substring(0, position1));
                ret[2] = (byte) Integer.parseInt(ipv4.substring(position1 + 1,
                        position2));
                ret[3] = (byte) Integer.parseInt(ipv4.substring(position2 + 1,
                        position3));
                ret[4] = (byte) Integer.parseInt(ipv4.substring(position3 + 1));
                return ret;
            }
            /**
             * @param ipAddress The IPv4 or IPv6 string.
             * @return 4 for IPv4, 6 for IPv6, or 0 for an invalid address.
             * @throws Exception
             */
            public static int isIpV4OrV6(String ipAddress) throws Exception {
                InetAddress address = InetAddress.getByName(ipAddress);
                if (address instanceof Inet4Address)
                    return 4;
                else if (address instanceof Inet6Address)
                    return 6;
                return 0;
            }
            /*
             * Checks whether an IP address is within a specified IP range.
             *
             * ipSection The IP range, separated by a hyphen (-).
             *
             * ip The IP address to validate.
             */
            public static boolean ipExistsInRange(String ip, String ipSection) {
                ipSection = ipSection.trim();
                ip = ip.trim();
                int idx = ipSection.indexOf('-');
                String beginIP = ipSection.substring(0, idx);
                String endIP = ipSection.substring(idx + 1);
                return getIp2long(beginIP) <= getIp2long(ip)
                        && getIp2long(ip) <= getIp2long(endIP);
            }
            public static long getIp2long(String ip) {
                ip = ip.trim();
                String[] ips = ip.split("\\.");
                long ip2long = 0L;
                for (int i = 0; i < 4; ++i) {
                    ip2long = ip2long << 8 | Integer.parseInt(ips[i]);
                }
                return ip2long;
            }
            public static long getIp2long2(String ip) {
                ip = ip.trim();
                String[] ips = ip.split("\\.");
                long ip1 = Integer.parseInt(ips[0]);
                long ip2 = Integer.parseInt(ips[1]);
                long ip3 = Integer.parseInt(ips[2]);
                long ip4 = Integer.parseInt(ips[3]);
                long ip2long = 1L * ip1 * 256 * 256 * 256 + ip2 * 256 * 256 + ip3 * 256
                        + ip4;
                return ip2long;
            }
            public static void main(String[] args) {
                System.out.println(StringToLong("2002:7af3:f3be:ffff:ffff:ffff:ffff:ffff"));
                System.out.println(StringToLong("54.38.XX.XX"));
            }
            private class Invalid{
                private Invalid()
                {
                }
            }
        }
                                                
      • IpV4Obj

        package com.aliyun.odps.udf.objects;
        public class IpV4Obj {
            public long startIp ;
            public long endIp ;
            public String city;
            public String province;
            public IpV4Obj(long startIp, long endIp, String city, String province) {
                this.startIp = startIp;
                this.endIp = endIp;
                this.city = city;
                this.province = province;
            }
            @Override
            public String toString() {
                return "IpV4Obj{" +
                        "startIp=" + startIp +
                        ", endIp=" + endIp +
                        ", city='" + city + '\'' +
                        ", province='" + province + '\'' +
                        '}';
            }
            public void setStartIp(long startIp) {
                this.startIp = startIp;
            }
            public void setEndIp(long endIp) {
                this.endIp = endIp;
            }
            public void setCity(String city) {
                this.city = city;
            }
            public void setProvince(String province) {
                this.province = province;
            }
            public long getStartIp() {
                return startIp;
            }
            public long getEndIp() {
                return endIp;
            }
            public String getCity() {
                return city;
            }
            public String getProvince() {
                return province;
            }
        }
                                                
      • IpV6Obj

        package com.aliyun.odps.udf.objects;
        public class IpV6Obj {
            public String startIp ;
            public String endIp ;
            public String city;
            public String province;
            public String getStartIp() {
                return startIp;
            }
            @Override
            public String toString() {
                return "IpV6Obj{" +
                        "startIp='" + startIp + '\'' +
                        ", endIp='" + endIp + '\'' +
                        ", city='" + city + '\'' +
                        ", province='" + province + '\'' +
                        '}';
            }
            public IpV6Obj(String startIp, String endIp, String city, String province) {
                this.startIp = startIp;
                this.endIp = endIp;
                this.city = city;
                this.province = province;
            }
            public void setStartIp(String startIp) {
                this.startIp = startIp;
            }
            public String getEndIp() {
                return endIp;
            }
            public void setEndIp(String endIp) {
                this.endIp = endIp;
            }
            public String getCity() {
                return city;
            }
            public void setCity(String city) {
                this.city = city;
            }
            public String getProvince() {
                return province;
            }
            public void setProvince(String province) {
                this.province = province;
            }
        }
                                                
  2. MaxCompute UDF kodunu yazın.

    1. Project bölmesinde modül kaynak dizinine (src > main > java) sağ tıklayın ve New > MaxCompute Java seçeneklerini seçin.

    2. Create new MaxCompute java class iletişim kutusunda UDF seçeneğine tıklayın, bir Name girin, Enter tuşuna basın ve ardından kod düzenleyicide kodu girin.

      Örneğin, Java sınıfına IpLocation adını verin. Aşağıdaki kodu değiştirmeden kullanabilirsiniz.

      package com.aliyun.odps.udf.udfFunction;
      import com.aliyun.odps.udf.ExecutionContext;
      import com.aliyun.odps.udf.UDF;
      import com.aliyun.odps.udf.UDFException;
      import com.aliyun.odps.udf.utils.IpUtils;
      import com.aliyun.odps.udf.objects.IpV4Obj;
      import com.aliyun.odps.udf.objects.IpV6Obj;
      import java.io.*;
      import java.util.ArrayList;
      import java.util.Comparator;
      import java.util.List;
      import java.util.stream.Collectors;
      public class IpLocation extends UDF {
          public static IpV4Obj[] ipV4ObjsArray;
          public static IpV6Obj[] ipV6ObjsArray;
          public IpLocation() {
              super();
          }
          @Override
          public void setup(ExecutionContext ctx) throws UDFException, IOException {
              //IPV4
              if(ipV4ObjsArray==null)
              {
                  BufferedInputStream bufferedInputStream = ctx.readResourceFileAsStream("ipv4.txt");
                  BufferedReader br = new BufferedReader(new InputStreamReader(bufferedInputStream));
                  ArrayList<IpV4Obj> ipV4ObjArrayList=new ArrayList<>();
                  String line = null;
                  while ((line = br.readLine()) != null) {
                      String[] f = line.split("\\|", -1);
                      if(f.length>=5)
                      {
                          long startIp = IpUtils.StringToLong(f[0]);
                          long endIp = IpUtils.StringToLong(f[1]);
                          String city=f[3];
                          String province=f[4];
                          IpV4Obj ipV4Obj = new IpV4Obj(startIp, endIp, city, province);
                          ipV4ObjArrayList.add(ipV4Obj);
                      }
                  }
                  br.close();
                  List<IpV4Obj> collect = ipV4ObjArrayList.stream().sorted(Comparator.comparing(IpV4Obj::getStartIp)).collect(Collectors.toList());
                  ArrayList<IpV4Obj> basicIpV4DataList=(ArrayList)collect;
                  IpV4Obj[] ipV4Objs = new IpV4Obj[basicIpV4DataList.size()];
                  ipV4ObjsArray = basicIpV4DataList.toArray(ipV4Objs);
              }
              //IPV6
              if(ipV6ObjsArray==null)
              {
                  BufferedInputStream bufferedInputStream = ctx.readResourceFileAsStream("ipv6.txt");
                  BufferedReader br = new BufferedReader(new InputStreamReader(bufferedInputStream));
                  ArrayList<IpV6Obj> ipV6ObjArrayList=new ArrayList<>();
                  String line = null;
                  while ((line = br.readLine()) != null) {
                      String[] f = line.split("\\|", -1);
                      if(f.length>=5)
                      {
                          String startIp = IpUtils.StringToBigIntString(f[0]);
                          String endIp = IpUtils.StringToBigIntString(f[1]);
                          String city=f[3];
                          String province=f[4];
                          IpV6Obj ipV6Obj = new IpV6Obj(startIp, endIp, city, province);
                          ipV6ObjArrayList.add(ipV6Obj);
                      }
                  }
                  br.close();
                  List<IpV6Obj> collect = ipV6ObjArrayList.stream().sorted(Comparator.comparing(IpV6Obj::getStartIp)).collect(Collectors.toList());
                  ArrayList<IpV6Obj> basicIpV6DataList=(ArrayList)collect;
                  IpV6Obj[] ipV6Objs = new IpV6Obj[basicIpV6DataList.size()];
                  ipV6ObjsArray = basicIpV6DataList.toArray(ipV6Objs);
              }
          }
          public String evaluate(String ip){
              if(ip==null||ip.trim().isEmpty()||!(ip.contains(".")||ip.contains(":")))
              {
                  return null;
              }
              int ipV4OrV6=0;
              try {
                  ipV4OrV6= IpUtils.isIpV4OrV6(ip);
              } catch (Exception e) {
                  return null;
              }
              // If the IP address is an IPv4 address.
              if(ipV4OrV6==4)
              {
                  int i = binarySearch(ipV4ObjsArray, IpUtils.StringToLong(ip));
                  if(i>=0)
                  {
                      IpV4Obj ipV4Obj = ipV4ObjsArray[i];
                      return ipV4Obj.city+","+ipV4Obj.province;
                  }else{
                      return null;
                  }
              }else if(ipV4OrV6==6)// If the IP address is an IPv6 address.
              {
                  int i = binarySearchIPV6(ipV6ObjsArray, IpUtils.StringToBigIntString(ip));
                  if(i>=0)
                  {
                      IpV6Obj ipV6Obj = ipV6ObjsArray[i];
                      return ipV6Obj.city+","+ipV6Obj.province;
                  }else{
                      return null;
                  }
              }else{// If the IP address is not in IPv4 or IPv6 format.
                  return null;
              }
          }
          @Override
          public void close() throws UDFException, IOException {
              super.close();
          }
          private static int binarySearch(IpV4Obj[] array,long ip){
              int low=0;
              int hight=array.length-1;
              while (low<=hight)
              {
                  int middle=(low+hight)/2;
                  if((ip>=array[middle].startIp)&&(ip<=array[middle].endIp))
                  {
                      return middle;
                  }
                  if (ip < array[middle].startIp)
                      hight = middle - 1;
                  else {
                      low = middle + 1;
                  }
              }
              return -1;
          }
          private static int binarySearchIPV6(IpV6Obj[] array,String ip){
              int low=0;
              int hight=array.length-1;
              while (low<=hight)
              {
                  int middle=(low+hight)/2;
                  if((ip.compareTo(array[middle].startIp)>=0)&&(ip.compareTo(array[middle].endIp)<=0))
                  {
                      return middle;
                  }
                  if (ip.compareTo(array[middle].startIp) < 0)
                      hight = middle - 1;
                  else {
                      low = middle + 1;
                  }
              }
              return -1;
          }
          private class Invalid{
              private Invalid()
              {
              }
          }
      }
                                      
  3. Yerel hata ayıklama için verileri hazırlayın.

    1. Yerel projenizin warehouse/example_project/__tables__/wc_in2/p1=2/p2=1/ dizininde data dosyasını açın.

    2. data dosyasındaki son sütundaki verileri ipv4.txt dosyasından alınan herhangi üç IP adresiyle değiştirin ve dosyayı kaydedin.

  4. Kodun başarıyla çalıştığından emin olmak için MaxCompute UDF'sinde hata ayıklayın.

    Daha fazla bilgi için UDF'yi yerel olarak çalıştırarak hata ayıklama konusuna bakın.

    1. Tamamlanan MaxCompute UDF betiğine sağ tıklayın ve Run seçeneğini seçin.

    2. Run/Debug Configurations iletişim kutusunda çalışma zamanı parametrelerini yapılandırın ve OK düğmesine tıklayın.

      Örnek olarak, Name alanını IpLocation ve Main class alanını com.aliyun.odps.udf.udfFunction.IpLocation olarak ayarlayın. MaxCompute'e özel alanlar için MaxCompute project alanında local ve example_project değerlerini seçin, MaxCompute table alanında wc_in2 değerini girin, Table partition alanında p1=v1,p2=v2 biçiminde p2=1,p1=2 değerini girin ve Table columns alanında c1,c2 biçiminde colc değerini girin. Download Record limit değerini 100 olarak ayarlayın ve Data Column Separator değerini virgül olarak belirleyin. Ardından OK düğmesine tıklayın. Kod hatasız çalışıyorsa devam edebilirsiniz. Aksi takdirde, IntelliJ IDEA'daki hata mesajını kullanarak sorunu giderin.

      Not

      Çalışma zamanı parametrelerine örnek olarak şekle bakabilirsiniz.

Adım 4: MaxCompute UDF'sini kaydedin

  1. Başarıyla derlenen MaxCompute UDF betiğine sağ tıklayın ve Deploy to server… seçeneğini seçin.

  2. Package a jar, submit resource and register function iletişim kutusunda parametreleri yapılandırın.

    Parametre açıklamaları için Paketleme, yükleme ve kaydetme konusuna bakın. Örnek olarak, MaxCompute project için hedef projenizi seçin. Resource file için paketlenmiş JAR dosyasını seçin. Resource name otomatik olarak doldurulur. Main class alanını UDF'nin tam nitelikli adına (örneğin com.aliyun.odps.udf.udfFunction.IpLocation) ayarlayın ve Function name alanına işlev için bir ad (örneğin ipv4_ipv6_aton) girin. Extra resources altında Adım 1 bölümünde yüklediğiniz ipv4.txt ve ipv6.txt dosyalarını seçin. Force update if already exists seçeneğini işaretleyin ve ardından OK düğmesine tıklayın.

Adım 5: IP adreslerini dönüştürmek için UDF'yi çağırın

  1. MaxCompute istemcisini yükleyin ve oturum açın.

  2. UDF'yi çağırarak IP adreslerini coğrafi konumlara dönüştürmek için bir SELECT deyimi çalıştırın.

    Örnekler:

    • Bir IPv4 adresini coğrafi konuma dönüştürme

      select ipv4_ipv6_aton('116.11.XX.XX');

      Beklenen çıktı:

      Beihai,Guangxi Zhuang Autonomous Region
    • Bir IPv6 adresini coğrafi konuma dönüştürme

      select ipv4_ipv6_aton('2001:0250:080b:0:0:0:0:0');

      Beklenen çıktı:

      Baoding,Hebei Province