使用GoQuery拆分元素

时间:2018-05-08 17:51:40

标签: go goquery

我正在尝试使用GoQuery从页面获取内容,但出于某些原因,我无法在换行符(br)上进行拆分。

HTML,如下所示:

<ul>
    <li>I'm skipped</li>

    <li> 
        Text Into  - <p>Whatever</p>
        <p>
            Line 1<br />
            Line 2<br />
            Line 3<br />
            Line 4<br />
            Line N
        </p>
    </li> 
</ul>

转到代码:

doc, err := goquery.NewDocumentFromReader(res.Body)
if err != nil {
    panic(err)
}

doc.Find("ul").Each(func(i int, s *goquery.Selection) {

    str := s.Find("li p").Next().Text()

    fmt.Println(str, "--")

})

出于某种原因,我无法将每个行(由p标记中的break分隔)作为单个项目。上面的代码输出为:

Line1Line2Line3Line4LineN--

但我想要实现的输出应该是这样的:

Line1--
Line2--
Line3--
Line4--
LineN--

由于我是新手,请在评论中告诉我如果有些事情不清楚,我会尽量解释它。

感谢。

4 个答案:

答案 0 :(得分:1)

我运行了你展示的代码,我在字符串中获取换行符。假设您使用的是最新版本的goquery,那么除非你的html不是

<p>
    Line 1<br />
    Line 2<br />
    Line 3<br />
    Line 4<br />
    Line N
</p>

但实际上是这样的:

<p>
    Line 1<br />Line 2<br />Line 3<br />Line 4<br />Line N
</p>

(请记住,例如,当您打开chrome dev工具时,它可能显示它作为前者,即使实际来源是后者)

在这种情况下,这是预期的行为:

&#13;
&#13;
let html_1 = $(`<p>
        Line 1<br />
        Line 2<br />
        Line 3<br />
        Line 4<br />
        Line N
    </p>`);

let html_2 = $(`<p>
        Line 1<br />Line 2<br />Line 3<br />Line 4<br />Line N
    </p>`);
    
console.log({html1: html_1.text(), html2: html_2.text()});
&#13;
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
&#13;
&#13;
&#13;

要解决,你可能只会这样做:

p := s.Find("li p").Next()
p.SetHtml(strings.Replace(p.Html(), "<br />", "<br />\n", -1)).Text()

但是,您可能需要使用<br/><br /><br>,因为我不确定它是如何呈现的。

答案 1 :(得分:1)

.Text()将:

  

Text获取集合中每个元素的组合文本内容   匹配的元素,包括它们的后代。

所以你真正想做的是获取内容并过滤掉任何br标签。正如戴夫的回答所说,那里有新的行字符,所以我也修剪了那些:

package main

import (
    "fmt"
    "github.com/PuerkitoBio/goquery"
    "strings"
)

var input string = `
<ul>
    <li>I'm skipped</li>

    <li> 
        Text Into  - <p>Whatever</p>
        <p>
            Line 1<br />
            Line 2<br />
            Line 3<br />
            Line 4<br />
            Line N
        </p>
    </li> 
</ul>
`

func main() {
    doc, err := goquery.NewDocumentFromReader(strings.NewReader(input))
    if err != nil {
        panic(err)
    }

    doc.Find("ul").Each(func(i int, s *goquery.Selection) {

        p := s.Find("li p").Next()
        p.Contents().Each(func(i int, s *goquery.Selection) {
            if !s.Is("br") {
                fmt.Println(strings.TrimSpace(s.Text()), "--")
            }

        })

    })
}

产地:

Line 1 --
Line 2 --
Line 3 --
Line 4 --
Line N --

答案 2 :(得分:0)

好的,我找到了一个解决方案。不确定如果这是正确的方法,所以如果有人有更好的东西 - 请分享。

所以我基本上将li p的值存储为HTML,然后使用strings.Split打破每个br标记,并且由于strings.Split返回字符串片段,我只是循环它。

title, err := s.Find("li p").Next().Html()
if err != nil {
    panic(err)
}

splittedTitles := strings.Split(title, "<br/>")

for _, str := range splittedTitles {
    fmt.Println(str, "--")
}

答案 3 :(得分:0)

我认为最好在调用<br/>方法之前将.Text()替换为'\ n'或'-'。

    // html is the result of `.Html()` method
    str := strings.Replace(html, "<br/>", "\\n", -1)
    doc, err := goquery.NewDocumentFromReader(strings.NewReader(str))
    if err != nil {
        return ""
    }
    return doc.Text()