我必须使用python开发一个Spark脚本,它检查一些日志并验证用户是否在两个事件之间更改了他的IP国家。我有一个csv文件,其IP范围和相关国家/地区保存在HDFS上,如下所示:
startIp, endIp, country
0.0.0.0, 10.0.0.0, Italy
10.0.0.1, 20.0.0.0, England
20.0.0.1, 30.0.0.0, Germany
还有一个log csv文件:
userId, timestamp, ip, event
1, 02-01-17 20:45:18, 10.5.10.3, login
24, 02-01-17 20:46:34, 54.23.16.56, login
我使用Spark Dataframe加载这两个文件,并且我已经使用滞后函数修改了包含日志的文件,并添加了一个包含previousIp的列。我认为解决方案是将ip和previousIp替换为关联国家,以便比较它们并使用dataFrame.filter(" previousIp"!=" ip")。 我的问题是,有一种方法可以在Spark中做到这一点?类似的东西:
dataFrame = dataFrame.select("userId", udfConvert("ip",countryDataFrame).alias("ip"), udfConvert("previousIp",countryDataFrame).alias("previousIp"),...)
为了拥有这样的Dataframe:
userId, timestamp, ip, event, previousIp
1, 02-01-17 20:45:18, England, login, Italy
如果没有,我怎么能解决我的问题?谢谢
答案 0 :(得分:1)
如果您先将IP地址转换为数字,这实际上非常简单。您可以编写自己的UDF或使用petrabarus中的代码并注册函数,如下所示:
spark.sql("CREATE TEMPORARY FUNCTION iptolong as 'net.petrabarus.hiveudfs.IPToLong'")
然后将国家/地区csv映射到带有数字的数据框:
>>> ipdb = spark.read.csv('ipdb.csv', header=True).select(
expr('iptolong(startIp)').alias('ip_from'),
expr('iptolong(endIp)').alias('ip_to'),
'country')
>>> ipdb.show()
+---------+---------+-------+
| ip_from| ip_to|country|
+---------+---------+-------+
| 0|167772160| Italy|
|167772161|335544320|England|
|335544321|503316480|Germany|
+---------+---------+-------+
另外,将日志数据框映射到数字:
>>> log = spark.createDataFrame([('15.0.0.1',)], ['ip']) \
.withColumn('ip', expr('iptolong(ip)'))
>>> log.show()
+---------+
| ip|
+---------+
|251658241|
+---------+
然后,您可以使用between
条件加入此数据框:
>>> log.join(broadcast(ipdb), log.ip.between(ipdb.ip_from, ipdb.ip_to)).show()
+---------+---------+---------+-------+
| ip| ip_from| ip_to|country|
+---------+---------+---------+-------+
|251658241|167772161|335544320|England|
+---------+---------+---------+-------+