我采用的是Hive 的 Transform 函数 + python 脚本实现
创建Hive表
// An highlighted block
CREATE TABLE `chinese`(
`c1` string,
`c2` string,
`c3` string,
`c4` string)
ROW FORMAT SERDE
'org.apache.hadoop.hive.serde2.lazy.LazySimpleSerDe'
WITH SERDEPROPERTIES (
'field.delim'='\t',
'serialization.format'='\t')
STORED AS INPUTFORMAT
'org.apache.hadoop.mapred.TextInputFormat'
OUTPUTFORMAT
'org.apache.hadoop.hive.ql.io.HiveIgnoreKeyTextOutputFormat'
这里要注意,ORC 、parquet 类型的表要自己测试,Text 文本我这边没啥问题。
导入数据
15801086777 张三 17岁 男
13803457168 李四 57岁 男
17803427561 王五 57岁 女
# 数据用 \t 制表符 分割。
load data local inpath '/root/3.csv' INTO TABLE CHINESE ;
hive> select * from chinese;
OK
15801086777 张三 17岁 男
13803457168 李四 57岁 男
17803427561 王五 67岁 女
Time taken: 0.098 seconds, Fetched: 3 row(s)
查看到数据已经进去了
查看 phone 解析模块
安装模块
使用pip安装:(这里要在每一个节点下安装)
pip install phone
使用:
>>> from phone import Phone
>>> p = Phone()
>>> p.find(1888888)
>>> {'province': '\xe5\x8c\x97\xe4\xba\xac', 'phone_type': '\xe7\xa7\xbb\xe5\x8a\xa8',
'city': '\xe5\x8c\x97\xe4\xba\xac', 'area_code': '010',
'phone': '1888888', 'zip_code': '100000'}
支持号段
13*,15*,18*,14[5,7],17[0,6,7,8]
改写成 分布式的 map 函数
parse_phone_map.py
# -*- coding: utf-8 -*-
import sys
from phone import Phone
p = Phone()
for line in sys.stdin:
phone = line.strip()
info_dic = p.find(phone)
#print(info_dic)
province = info_dic.get('province') or ''
phone_type = info_dic.get('phone_type') or ''
city = info_dic.get('city') or ''
area_code = info_dic.get('area_code') or ''
phone = info_dic.get('phone') or ''
zip_code = info_dic.get('zip_code') or ''
print '\t'.join([province,phone_type,city,area_code,phone,zip_code])
本地测试 map 逻辑
[root@cdh00 hive-python]# cat 1.csv | awk '{print $1}' | python parse_phone_map.py
北京 移动 北京 010 15801086777 100000
山西 移动 太原 0351 13803457168 030000
山西 移动 晋城 0356 17803427561 048000
测试结果完全正确
集群上运行
# 添加 python 的 map 文件给 hive。
hive> ADD FILE /root/tmp/hive-python/parse_phone_map.py;
hive> SELECT TRANSFORM (c1) USING 'python parse_phone_map.py' AS (province, phone_type, city, area_code,phone,zip_code) FROM chinese ;
############### 结果如下 ################
Total MapReduce CPU Time Spent: 2 seconds 250 msec
OK
北京 移动 北京 010 15801086777 100000
山西 移动 太原 0351 13803457168 030000
山西 移动 晋城 0356 17803427561 048000
Time taken: 23.614 seconds, Fetched: 3 row(s)
# 或者调用 spark 引擎跑更快
hive> set hive.execution.engine=spark;
# 或者是查询出来直接插入到指定有该字段的表当中
hive> INSERT INTO TABLE u_data_new
SELECT TRANSFORM (c1) USING 'python parse_phone_map.py'
AS (province, phone_type, city, area_code,phone,zip_code)
FROM chinese ;
注意的一些坑
1、本来也想用 java 那套来做,但是本人好久没写 java 了,各种打包,依赖,以及用的第三方的包的源码使用 lombok 注解,导致最后 Hive 查询总是乱码。
2、python 的 phone 模块很久没有 更新了。官网的 phone.dat 数据最新是 2020.04的,建议下载最新的包下来。