Go:regexp FindAll和ReplaceAll一次通过

时间:2013-12-06 22:05:42

标签: regex go

我正在解析网页以获取标签内的一些值,但我对标签不感兴趣,只对内容感兴趣。

我使用regexp.FindAll获取所有匹配的表达式(包括标签),然后使用ReplaceAll替换每个子表达式,删除标签。当然,运行正则表达式需要两倍的时间,并且我想避免它。

是否有办法同时应用这两个函数,或同等的正则表达式?

当然,我可以创建一个删除标签的功能,但在某些情况下可能会因为可变长度标签(如)而更加复杂,正则表达式可以解决这个问题。

我的代码的一个简单示例就在这里(它不会在操场上运行):http://play.golang.org/p/uGKjzmylSY

func main() {
    res, err := http.Get("http://www.elpais.es")
    if err != nil {
        panic(err)
    }

    body, err := ioutil.ReadAll(res.Body)
    fmt.Println("body: ", len(body), cap(body))
    res.Body.Close()
    if err != nil {
        panic(err)
    }

    r := regexp.MustCompile("<li>(.+)</li>")

    // Find all subexpressions, containing the label <li>
    out := r.FindAll(body, -1)

    for i, v := range out[:10] {
        fmt.Printf("%d: %s\n", i, v)
    }

    //Replace to remove the label.
    out2 := make([][]byte, len(out))
    for i, v := range out {
        out2[i] = r.ReplaceAll(v, []byte("$1"))
    }

    for i, v := range out2[:10] {
        fmt.Printf("%d: %s\n", i, v)
    }
}

顺便说一句,我知道正则表达式不能用于解析HTML。我只对一些最里面的标签感兴趣,而不是对结构或嵌套感兴趣,所以我认为没关系:)

1 个答案:

答案 0 :(得分:5)

建议:使用goquery执行该任务,使用起来非常简单,并且减少了很多代码。 例如:

doc, _ := goquery.NewDocument("http://www.elpais.es")
text := doc.Find("li").Slice(10, -1).Text()

关于您的问题,请使用FindAllSubmatch直接提取匹配项:

r := regexp.MustCompile("<li>(.+)</li>")

// Find all subexpressions, containing the label <li>
out := r.FindAllSubmatch(body, -1)

for i, v := range out[:10] {
    fmt.Printf("%d: %s\n", i, v[1])
}