使用Scala匹配String中的href

时间:2016-08-17 22:22:46

标签: regex scala

使用此正则表达式(<a[^>]+>.+?<\\/a>)我尝试打印匹配的链接。

因此应打印t1,t2,t3但不打印任何内容:

val str = "tester<a href=\"t1\">this is just test text<a href=\"t2\">\\r\\t\\s<a href=\"t3\">"
val re = "(<a[^>]+>.+?<\\/a>)".r
for (p <- re findAllIn str) p match {
  case re(b) => print(b)
}

正则表达式或正则表达式的实现方式是不正确的?

更新:

使用已接受的答案,这将从网址下载所有有效的href(以&#39; http&#39;开头),在本例中为https://news.ycombinator.com/

import scala.io.Source
import org.jsoup.Jsoup
import org.jsoup.nodes.Document
import scala.collection.JavaConversions._

object Main extends App {

  val hrefs = getHrefsFromPage("https://news.ycombinator.com/");

  hrefs.foreach(e => println(e))

  def getHrefsFromPage(url: String): List[(String, String)] = {

    val doc = Jsoup.parse(Source.fromURL(url).mkString)
    val aTags = doc.select("a").iterator.toList
    val ts = (for (t <- aTags) yield (t.attr("href"), t.text))
    val fts = ts.filter(f => f._1.trim.startsWith("http"))

    return fts;
  }

}

1 个答案:

答案 0 :(得分:2)

Read this SO Answer first please.

现在回来了。

  

你需要使用一个可靠的html解析器来解析html字符串,在大多数非平凡的情况下,正则表达式都不够。

正则表达不会因为

而完成工作
  • 容易出错,我们一直在写正则表达式的错误,而且你只是验证者和维护者(维护噩梦)
  • 难以维护和记录
  • 难以测试,您必须考虑正则表达式的所有可能的测试用例字符串,然后为其编写测试用例。

为什么Html解析器更好

  • 不容易出错,已由多个贡献者和用户验证,与您只使用和验证的正则表达式不同

  • 在自己的网站上记录和javadoc

  • Html在库中解析已经过测试,您可以专注于测试您的应用功能或业务用例。

  • CSS选择器和DOM结构,用于选择和操作Html。 (这是最大的好处,你需要css选择器支持任何严肃的HTML工作。)

因此,我建议您使用Jsoup html parser。下面我将描述您案例的用法。

首先获取依赖或者只是下载jar。 Maven依赖如下:

<dependency>
    <groupId>org.jsoup</groupId>
    <artifactId>jsoup</artifactId>
    <version>1.9.2</version>
</dependency>

接下来是导入

import org.jsoup.Jsoup
import org.jsoup.nodes.Document

现在解析你的html字符串

val str = "tester<a href=\"t1\">this is just test text<a href=\"t2\">\\r\\t\\s<a href=\"t3\">"
val doc = Jsoup.parse(str)

这给出了什么:

doc: org.jsoup.nodes.Document =
<html>
 <head></head>
 <body>
  tester
  <a href="t1">this is just test text</a>
  <a href="t2">\r\t\s</a>
  <a href="t3"></a>
 </body>
</html>

请注意使用字符串中已清理标记生成的完整结构。

获取所有<a>代码

val aTags = doc.select("a")

结果:

aTags: org.jsoup.select.Elements =
<a href="t1">this is just test text</a>
<a href="t2">\r\t\s</a>
<a href="t3"></a>

获取所有<a>标记字符串表示

val aTagsString = aTags.toString

结果:

aTagsString: String =
<a href="t1">this is just test text</a>
<a href="t2">\r\t\s</a>
<a href="t3"></a>

获取第一个或第0个<a>代码

val firstATag = doc.select("a").get(0)

结果:

firstATag: org.jsoup.nodes.Element = <a href="t1">this is just test text</a>

获取第一个<a>代码

的字符串表示形式
val firstATagString = firstATag.toString

结果:

firstATagString: String = <a href="t1">this is just test text</a>

获取firstATag的内部文本(第0个<a>标记)

val firstATagInnerText = firstATag.text

结果:

firstATagInnerText: String = this is just test text

注意:即使你的标签没有关闭,这个解析器工作正常。虽然你的正则表达式实现失败了这个边缘情况。