使用Spark以CSV格式提取部分字符串

时间:2016-01-28 16:57:21

标签: scala apache-spark apache-spark-sql

在这里点火新手,希望你们能给我一些帮助。谢谢!

我正在尝试从CSV文件中提取URL,并且URL位于第16列。问题是URL是以一种奇怪的格式编写的,正如您从下面的代码中打印出来的那样。获取正确格式的URL的最佳方法是什么?

case class log(time_stamp: String, url: String )

val logText = sc.textFile("hdfs://...").map(s => s.split(",")).map( s => log(s(0).replaceAll("\"", ""),s(15).replaceAll("\"", ""))).toDF()


logText.registerTempTable("log")

val results = sqlContext.sql("SELECT * FROM log")
results.map(s => "URL: " + s(1)).collect().foreach(println)

URL: /XXX/YYY/ZZZ/http/www.domain.com/xyz/xyz
URL: /XX/YYY/ZZZ/https/sub.domain.com/xyz/xyz/xyz/xyz
URL: /XXX/YYY/ZZZ/http/www.domain.com/
URL: /VV/XXXX/YYY/ZZZ/https/sub.domain.com/xyz/xyz/xyz

2 个答案:

答案 0 :(得分:6)

您可以尝试regexp_replace

import org.apache.spark.sql.functions.regexp_replace

val df = sc.parallelize(Seq(
  (1L, "/XXX/YYY/ZZZ/http/www.domain.com/xyz/xyz"),
  (2L, "/XXX/YYY/ZZZ/https/sub.domain.com/xyz/xyz/xyz/xyz")
)).toDF("id", "url")

df
  .select(regexp_replace($"url", "^(/\\w+){3}/(https?)/", "$2://").alias("url"))
  .show(2, false)

// +--------------------------------------+
// |url                                   |
// +--------------------------------------+
// |http://www.domain.com/xyz/xyz         |
// |https://sub.domain.com/xyz/xyz/xyz/xyz|
// +--------------------------------------+

在Spark 1.4中,您可以尝试使用Hive UDF:

df.selectExpr("""regexp_replace(url, '^(/\w+){3}/(https?)/','$2://') AS url""")

如果http(s)之前的部分数量有所不同,则可以通过将{3}替换为*或范围来调整正则表达式。

答案 1 :(得分:0)

问题归结为解析长字符串并提取域名。只要您没有任何随机字符串(XXX,YYYYY等)为“http”和“https”,此解决方案就可以正常工作:

def getUrl(data: String): Option[String] = {
   val slidingPairs = data.split("/").sliding(2)
   slidingPairs.flatMap{ 
       case Array(x,y) => 
          if(x=="http" || x == "https") Some(y) else None
    }.toList.headOption
}

以下是REPL中的一些示例:

scala> getUrl("/XXX/YYY/ZZZ/http/www.domain.com/xyz/xyz")
res8: Option[String] = Some(www.domain.com)

scala> getUrl("/XXX/YYY/ZZZ/https/sub.domain.com/xyz/xyz/xyz/xyz")
resX: Option[String] = Some(sub.domain.com)

scala> getUrl("/XXX/YYY/ZZZ/a/asdsd/asdase/123123213/https/sub.domain.com/xyz/xyz/xyz/xyz")
resX: Option[String] = Some(sub.domain.com)