掘金 后端 ( ) • 2024-04-28 11:15

个人博客:无奈何杨(wnhyang)

个人语雀:wnhyang

共享语雀:在线知识共享

Github:wnhyang - Overview


简介

本篇文章是风控系统之数据服务,名单、标签、IP、设备、地理信息、征信等的扩展。

既然是上篇文章的扩展,自然离不开风控系统的主题。身份证和手机号解析作为风控事件接入的靠前的步骤是重要的数据处理过程,也是相对最简单的处理过程(与IP、GPS解析相比的话)。

Hutool.IdcardUtil

身份证工具-IdcardUtil | Hutool

HutoolIdcardUtil现在支持大陆15位、18位身份证,港澳台10位身份证。

工具中主要的方法包括:

  1. isValidCard 验证身份证是否合法
  2. convert15To18 身份证15位转18位
  3. getBirthByIdCard 获取生日
  4. getAgeByIdCard 获取年龄
  5. getYearByIdCard 获取生日年
  6. getMonthByIdCard 获取生日月
  7. getDayByIdCard 获取生日天
  8. getGenderByIdCard 获取性别
  9. getProvinceByIdCard 获取省份

此工具中包含了国内身份证的规定和验证说明。基本的身份证解析功能都具备了,缺点就是关于身份证归属地只到省级别。

中国行政区划

身份证的前6位表示省/市/县,Hutool也已经说明了,而且将省份及其对应编码放入了静态Map中了,可能出于内存和行政区划变动的原因,并没有将市/县囊括在内。

https://www.mca.gov.cn/mzsj/xzqh/2022/202201xzqh.html

GitHub - modood/Administrative-divisions-of-China: 中华人民共和国行政区划:省级(省份)、 地级(城市)、 县级(区县)、 乡级(乡镇街道)、 村级(村委会居委会) ,中国省市区镇村二级三级四级五级联动地址数据。

非常建议通过这个Github项目来更新中国行政区划数据,该项目提供了jsoncsv格式的数据,而且数据也比较新。

以下是通过内存加载省/市/县的示例,因为到县级别数量也不是很大,就放在内存中吧,快嘛。

使用到了provinces.csvcities.csvareas.csv都可以通过Github下载。

/**
 * <a href="https://github.com/modood/Administrative-divisions-of-China">...</a>
 * @author wnhyang
 * @date 2024/4/24
 **/
@Slf4j
public class AdocUtil {

    private static final Map<String, Province> PROVINCE_MAP = new HashMap<>(32);

    private static final Map<String, City> CITY_MAP = new HashMap<>(512);

    private static final Map<String, Area> AREA_MAP = new HashMap<>(4096);

    private static final String DONT_KNOW = "未知";

    private static final int AREA_CODE_LENGTH = 6;

    private AdocUtil() {
    }

    public static void init() {
        long start = System.currentTimeMillis();
        try {
            List<Province> provinceList = CsvUtil.getReader().read(
                    ResourceUtil.getUtf8Reader("provinces.csv"), Province.class);
            provinceList.forEach(province -> PROVINCE_MAP.put(province.getCode(), province));

            List<City> cityList = CsvUtil.getReader().read(
                    ResourceUtil.getUtf8Reader("cities.csv"), City.class);
            cityList.forEach(city -> CITY_MAP.put(city.getCode(), city));

            List<Area> areaList = CsvUtil.getReader().read(
                    ResourceUtil.getUtf8Reader("areas.csv"), Area.class);
            areaList.forEach(area -> AREA_MAP.put(area.getCode(), area));

        } catch (Exception e) {
            throw new RuntimeException(e);
        }
        log.info("init success, cost:{}ms", System.currentTimeMillis() - start);
    }

}

手机号的解析

手机号码的归属地可以通过号码的前七位进行判断。前三位如170/150/136等是网络识别号,中间四位是地区编码(归属地),最后四位是用户号码。因此,正确念读手机号的方法是:1xx-xxxx-xxxx。中国大陆地区手机号码格式为:1**####$$$$。星号部分(*)用于区分不同的业务服务提供商,例如移动、联通和电信等。前七位(1**####)可以用来查出手机的归属地。

可参考以下项目。

GitHub - fighting41love/funNLP

GitHub - ls0f/phone: 手机号码归属地库

GitHub - xluohome/phonedata: 手机号码归属地信息库、手机号归属地查询 phone.dat 最后更新:2023年02月

GitHub - fengjiajie/phone-number-geo: 手机号码归属地本地解析(Java)

GitHub - EeeMt/phone-number-geo: 离线查询手机号归属地

GitHub - AfterShip/phone: With a given country and phone number, validate and reformat the mobile phone number to the E.164 standard. The purpose of this is to allow us to send SMS to mobile phones only.

关于开源项目的使用,一般要从代码质量文档、许可证、使用社区活跃度、性能多方面来考虑。

以下是GitHub - EeeMt/phone-number-geo: 离线查询手机号归属地的一个简单示例。

/**
 * @author wnhyang
 * @date 2024/4/26
 **/
@Slf4j
public class PhoneNumberUtil {

    private static final PhoneNumberLookup LOOKUP = new PhoneNumberLookup();

    private static final String DONT_KNOW = "未知";

    private PhoneNumberUtil() {
    }

    public static PhoneNumberInfo lookup(String phoneNumber) {
        return LOOKUP.lookup(phoneNumber).orElseGet(() -> getNotFound(phoneNumber));
    }

    public static PhoneNumberInfo getNotFound(String phoneNumber) {
        return new PhoneNumberInfo(phoneNumber, new Attribution(DONT_KNOW, DONT_KNOW, DONT_KNOW, DONT_KNOW), ISP.UNKNOWN);
    }
}

写在最后

拙作艰辛,字句心血,望诸君垂青,多予支持,不胜感激。


个人博客:无奈何杨(wnhyang)

个人语雀:wnhyang

共享语雀:在线知识共享

Github:wnhyang - Overview