java学习笔记(三)手机号码归属地批量查询的代码,亲测可用

重要的事情说一遍,注意本代码实现的优点是批量查询!!!
当前单个手机号码查询也是没有问题的。
由于公司行业主要是展会行业,展会上的观众注册等,填写基本信息的时候会采集手机号等信息,展会结束后我们需要做数据分析。只有通过手机号查找归属地来获取客户的地域信息。找了好多平台和api,发现没有说是能批量处理手机号信息。最后还是找了githup上找到一个插件,感谢那位大神的贡献。

传送门> https://github.com/xluohome/phonedata
主要涉及到两个类和一个dat文件
PhoneNumberGeo.java 和 PhoneNumberInfo.java 以及一个 phone.dat文件(存放手机归属信息的),dat文件可在传送门里面找到。
PhoneNumberGeo.java 文件内容如下,主要作用是来读取phone.dat文件。

package com.yh.util.phone;

import java.io.ByteArrayOutputStream;
import java.io.InputStream;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.nio.charset.StandardCharsets;
import java.util.Scanner;

/**
 * Created by buring 18/10/12.
 */
public class PhoneNumberGeo {

  private static String[] numberType = {null, "移动", "联通", "电信", "电信虚拟运营商", "联通虚拟运营商", "移动虚拟运营商"};
  private static final int INDEX_SEGMENT_LENGTH = 9;

  private static byte[] dataByteArray;
  private ByteBuffer byteBuffer;
  private int indexAreaOffset = -1;
  private int phoneRecordCount = -1;

  public PhoneNumberGeo() {
    if (dataByteArray == null) {
      synchronized (PhoneNumberGeo.class) {
        if (dataByteArray == null) {
          ByteArrayOutputStream byteData = new ByteArrayOutputStream();
          byte[] buffer = new byte[1024];

          int readBytesLength;
          try {
        	  InputStream inputStream = PhoneNumberGeo.class
                      .getResourceAsStream("phone.dat");
            while ((readBytesLength = inputStream.read(buffer)) != -1) {
              byteData.write(buffer, 0, readBytesLength);
            }
            inputStream.close();
          } catch (Exception e) {
            System.err.println("Can't find phone.dat in classpath:phone-number-geo/phone.dat");
            e.printStackTrace();
            throw new RuntimeException(e);
          }

          dataByteArray = byteData.toByteArray();
        }
      }
    }

    byteBuffer = ByteBuffer.wrap(dataByteArray);
    byteBuffer.order(ByteOrder.LITTLE_ENDIAN);
    int dataVersion = byteBuffer.getInt();
    indexAreaOffset = byteBuffer.getInt();

    // print data version
    // System.out.println(dataVersion);

    phoneRecordCount = (dataByteArray.length - indexAreaOffset) / INDEX_SEGMENT_LENGTH;
    // print record count
    // System.out.println(phoneRecordCount);
  }

  public PhoneNumberInfo lookup(String phoneNumber) {
    if (phoneNumber == null || phoneNumber.length() > 11 || phoneNumber.length() < 7) {
      return null;
    }
    int phoneNumberPrefix;
    try {
      phoneNumberPrefix = Integer.parseInt(phoneNumber.substring(0, 7));
    } catch (Exception e) {
      return null;
    }
    int left = 0;
    int right = phoneRecordCount;
    while (left <= right) {
      int middle = (left + right) >> 1;
      int currentOffset = indexAreaOffset + middle * INDEX_SEGMENT_LENGTH;
      if (currentOffset >= dataByteArray.length) {
        return null;
      }

      byteBuffer.position(currentOffset);
      int currentPrefix = byteBuffer.getInt();
      if (currentPrefix > phoneNumberPrefix) {
        right = middle - 1;
      } else if (currentPrefix < phoneNumberPrefix) {
        left = middle + 1;
      } else {
        int infoBeginOffset = byteBuffer.getInt();
        int phoneType = byteBuffer.get();

        int infoLength = -1;
        for (int i = infoBeginOffset; i < indexAreaOffset; ++i) {
          if (dataByteArray[i] == 0) {
            infoLength = i - infoBeginOffset;
            break;
          }
        }

        String infoString =
            new String(dataByteArray, infoBeginOffset, infoLength, StandardCharsets.UTF_8);
        String[] infoSegments = infoString.split("\\|");

        PhoneNumberInfo phoneNumberInfo = new PhoneNumberInfo();
        phoneNumberInfo.setPhoneNumber(phoneNumber);
        phoneNumberInfo.setProvince(infoSegments[0]);
        phoneNumberInfo.setCity(infoSegments[1]);
        phoneNumberInfo.setZipCode(infoSegments[2]);
        phoneNumberInfo.setAreaCode(infoSegments[3]);
        phoneNumberInfo.setPhoneType(numberType[phoneType]);
        return phoneNumberInfo;
      }
    }
    return null;
  }

  public static void main(String[] args) {
    PhoneNumberGeo phoneNumberGeo = new PhoneNumberGeo();
    Scanner scanner = new Scanner(System.in);
    while (scanner.hasNext()) {
      System.out.println(phoneNumberGeo.lookup(scanner.next()));
    }
  }
}

PhoneNumberInfo.java 文件内容如下,主要作用 定义一个model

package com.yh.util.phone;

public class PhoneNumberInfo {
  private String phoneNumber;
  private String province;
  private String city;
  private String zipCode;
  private String areaCode;
  private String phoneType;

  public String getPhoneNumber() {
    return phoneNumber;
  }

  public void setPhoneNumber(String phoneNumber) {
    this.phoneNumber = phoneNumber;
  }

  public String getProvince() {
    return province;
  }

  public void setProvince(String province) {
    this.province = province;
  }

  public String getCity() {
    return city;
  }

  public void setCity(String city) {
    this.city = city;
  }

  public String getZipCode() {
    return zipCode;
  }

  public void setZipCode(String zipCode) {
    this.zipCode = zipCode;
  }

  public String getAreaCode() {
    return areaCode;
  }

  public void setAreaCode(String areaCode) {
    this.areaCode = areaCode;
  }

  public String getPhoneType() {
    return phoneType;
  }

  public void setPhoneType(String phoneType) {
    this.phoneType = phoneType;
  }

  @Override public String toString() {
    return "PhoneNumberInfo{" +
        "phoneNumber='" + phoneNumber + '\'' +
        ", province='" + province + '\'' +
        ", city='" + city + '\'' +
        ", zipCode='" + zipCode + '\'' +
        ", areaCode='" + areaCode + '\'' +
        ", phoneType='" + phoneType + '\'' +
        '}';
  }
}

文件存放路径建议
在这里插入图片描述
调用的代码如下,这段代码可以放在for循环里面去执行,效率肯定比单个去请求开放的API效率高很多,已经测试过好几批手机号数据(均为7000+条以上),查询不到的也就剩下几十条,这个可以单独去请求开放API获得手机号码归属地,我这里没有,可以自行搜索相关实现方法。

	String phoneNum = '13609257706'
	PhoneNumberGeo phoneNumberGeo = new PhoneNumberGeo();
	PhoneNumberInfo phoneNumberInfo = phoneNumberGeo.lookup(val);
	if(null!=phoneNumberInfo){
		//获取省份
		String province = phoneNumberInfo.getProvince();
		//获取城市 需要其他的参数自行查找PhoneNumberInfo类获取
		String city = phoneNumberInfo.getCity();
		System.out.println(province+"\t"+city);
	 }else{
	    	System.out.println("请单独去查询");
	 }

有问题请随时@我,邮箱[email protected]

猜你喜欢

转载自blog.csdn.net/buring_GG/article/details/83111118