2016-08-17 63 views
0

使用此正则表达式(<a[^>]+>.+?<\\/a>)我试图打印匹配的链接。使用斯卡拉匹配字符串内的hrefs

所以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从URL(以 'http' 开头),在这种情况下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; 
    } 

} 
+0

强制性SO链接:http://stackoverflow.com/questions/1732348/regex-match-open-tags-except-xhtml-self-contained-tags/1732454#1732454。阅读我的答案,看看解析html的替代方法。请不要用正则表达式解析html。 Html不是一种常规语言,所以正则表达式解析是不可靠的(英语语言是有限的,因此是规则的,所以我们在那里使用正则表达式)。 – faizan

回答

2

Read this SO Answer first please.

现在回来了。

您需要使用可靠的html解析器库来解析html字符串,在大多数非平凡的情况下,regex将不够用。

正则表达式不会把工作做好,因为

  • 它很容易出错,我们犯错误写的正则表达式所有的时间,再加上你是TGE只验证和维护(维护的噩梦)
  • 这是难以维持和文件
  • 这是很难测试 ,你必须为你的正则表达式考虑所有可能的测试用例字符串,然后为它编写测试用例。

为什么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 

注意:即使您的标记不是关闭t他的解析器工作正常。虽然你的正则表达式实现失败了这个边缘情况。

+0

感谢您的详细信息,ive将我的解决方案发布到您的代码上。 –

+0

@ blue-sky:很高兴能帮到你。 :) – faizan