在简单的正则替换上获得NPE(Scala在Spark上)



我写了一个简单的代码来解析大型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; } 

我试图使用以下内容提取它们,但没有用:

"{[^}]+}"

最新更新