我写了一个简单的代码来解析大型XML文件(提取行,干净的文本,然后从中删除任何HTML标签(使用Apache Spark。
在字符串上调用 .replaceAllIn
时,我会看到一个nullpointerexception。
有趣的是,我在本地运行代码时没有错误,使用磁盘输入,但是当我在AWS EMR上运行相同代码时,我会得到NullPointerException
,加载输入文件来自S3。
这是相关代码:
val HTML_TAGS_PATTERN = """<[^>]+>""".r
// other code here...
spark
.sparkContext
.textFile(pathToInputFile, numPartitions)
.filter { str => str.startsWith(" <row ") }
.toDS()
.map { str =>
Locale.setDefault(new Locale("en", "US"))
val parts = str.split(""""""")
var title: String = ""
var body: String = ""
// some code ommitted here
title = StringEscapeUtils.unescapeXml(title).toLowerCase.trim
body = StringEscapeUtils.unescapeXml(body).toLowerCase // decode xml entities
println("before replacing, body is: "+body)
// NEXT LINE TRIGGERS NPE
body = HTML_TAGS_PATTERN.replaceAllIn(body, " ") // take out htmltags
}
我尝试过的事情:
在调用
replaceAllIn
之前,打印字符串以确保它不是null
。确保语言环境不是null
打印出异常消息,然后stacktrace:它只是告诉我那行是NullPoInterException的位置。没什么
我本地设置和AWS EMR之间有所不同的事物:
在我的本地设置中,我从磁盘上加载输入文件,在EMR上我从S3加载它。
在我的本地设置中,我以独立模式运行Spark,在EMR上以集群模式运行。
我的机器和AWS EMR上的其他所有内容都是相同的:Scala版本,Spark版本,Java版本,群集配置...
我一直在试图弄清楚这几个小时,我想不出其他任何尝试。
编辑
我已经将电话转移到r()
到map{}
主体内:
val HTML_TAGS_PATTERN = """<[^>]+>"""
// code ommited
.map{
body = HTML_TAGS_PATTERN.r.replaceAllIn(body, " ")
}
这也会产生 npe ,以下stracktrace:
java.lang.NullPointerException
at java.util.regex.Pattern.<init>(Pattern.java:1350)
at java.util.regex.Pattern.compile(Pattern.java:1028)
at scala.util.matching.Regex.<init>(Regex.scala:191)
at scala.collection.immutable.StringLike$class.r(StringLike.scala:255)
at scala.collection.immutable.StringOps.r(StringOps.scala:29)
at scala.collection.immutable.StringLike$class.r(StringLike.scala:244)
at scala.collection.immutable.StringOps.r(StringOps.scala:29)
at ReadSOStanfordTokenize$$anonfun$2.apply(ReadSOStanfordTokenize.scala:102)
at ReadSOStanfordTokenize$$anonfun$2.apply(ReadSOStanfordTokenize.scala:72)
at org.apache.spark.sql.catalyst.expressions.GeneratedClass$GeneratedIterator.processNext(Unknown Source)
at org.apache.spark.sql.execution.BufferedRowIterator.hasNext(BufferedRowIterator.java:43)
at org.apache.spark.sql.execution.WholeStageCodegenExec$$anonfun$8$$anon$1.hasNext(WholeStageCodegenExec.scala:377)
at org.apache.spark.sql.execution.datasources.FileFormatWriter$SingleDirectoryWriteTask.execute(FileFormatWriter.scala:243)
at org.apache.spark.sql.execution.datasources.FileFormatWriter$$anonfun$org$apache$spark$sql$execution$datasources$FileFormatWriter$$executeTask$3.apply(FileFormatWriter.scala:190)
at org.apache.spark.sql.execution.datasources.FileFormatWriter$$anonfun$org$apache$spar
我认为您应该尝试将正则透视式插入bellow。
这是一个la脚的解决方案,您应该能够定义一个常数,也许将其放在全局object
或其他地方。我不确定您在哪里定义它将是一个问题。但是请记住Spark会序列化代码并将其运行在分布式工人上,因此可能出了点问题。
rdd.map { _ =>
...
body = """<[^>]+>""".r.replaceAllIn(body, " ")
}
在空字符串上运行.r
时,我会遇到非常相似的错误。
val x: String = null
x.r
java.lang.NullPointerException
java.util.regex.Pattern.<init>(Pattern.java:1350)
java.util.regex.Pattern.compile(Pattern.java:1028)
scala.util.matching.Regex.<init>(Regex.scala:223)
scala.collection.immutable.StringLike.r(StringLike.scala:281)
scala.collection.immutable.StringLike.r$(StringLike.scala:281)
scala.collection.immutable.StringOps.r(StringOps.scala:29)
scala.collection.immutable.StringLike.r(StringLike.scala:270)
scala.collection.immutable.StringLike.r$(StringLike.scala:270)
scala.collection.immutable.StringOps.r(StringOps.scala:29)
我认为,由于Scala版本,该错误的行号略有不同。im在2.12.2。
感谢Stephen的答案,我发现了为什么我在UDF上得到NPE ...我去了(在我的情况下找到一场比赛(:
def findMatch(word: String): String => Boolean = { s =>
Option(s) match {
case Some(validText) => if (word.toLowerCase.r.findAllIn(validText.toLowerCase).nonEmpty) true else false
case None => false
}
}
"&lt; [^>]>"很棒,但是我的html中有一种类型的东西。它由样式的名称组成,然后在卷曲括号之间的参数组成:
p { margin-top: 0px;margin-bottom: 0px;line-height: 1.15; }
body { font-family: 'Arial';font-style: Normal;font-weight: normal;font-size: 14.6666666666667px; }.Normal { telerik-style-type: paragraph;telerik-style-name: Normal;border-collapse: collapse; }.TableNormal { telerik-style-type: table;telerik-style-name: TableNormal;border-collapse: collapse; }.s_4C87DD5E { telerik-style-type: local;font-family: 'Arial';font-size: 14.6666666666667px;color: #000000; }.s_8D20FCAB { telerik-style-type: local;font-family: 'Arial';font-size: 14.6666666666667px;color: #000000;text-decoration: underline; }.p_53E06EE5 { telerik-style-type: local;margin-left: 0px; }
我试图使用以下内容提取它们,但没有用:
"{[^}]+}"