goquery- 从一个 html 标签中提取文本并将其添加到下一个标签

goquery- Extract text from one html tag and add it to the next tag

是的,很抱歉标题没有解释任何内容。我需要举个例子。

这是我发布的另一个 的延续,它解决了一个问题,但不是所有问题。我已将该问题的大部分背景信息放入这个问题中。此外,我只研究了大约 5 天的 Go(我几个月前才开始学习代码),所以我 90% 确定我已经接近弄清楚我想要什么,问题是我有一些愚蠢的语法错误。

情况

我正在尝试使用 goquery 来解析网页。 (最终我想把一些数据放在数据库中)。这是它的样子:

<html>
    <body>
        <h1>
            <span class="text">Go </span>
        </h1>
        <p>
            <span class="text">totally </span>
            <span class="post">kicks </span>
        </p>
        <p>
            <span class="text">hacks </span>
            <span class="post">its </span>
        </p>
        <h1>
            <span class="text">debugger </span>
        </h1>
        <p>
            <span class="text">should </span>
            <span class="post">be </span>
        </p>
        <p>
            <span class="text">called </span>
            <span class="post">ogle </span>
        </p>
        <h3>
            <span class="statement">true</span>
        </h3>
    </body>
<html>

Objective

我愿意:

  1. 提取<h1..."text"的内容。
  2. 将提取的内容插入(并连接)到 <p..."text" 的内容中。
  3. 仅对 紧跟 <h1> 标签的 <p> 标签执行此操作。
  4. 对页面上 <h1> 标签中的 所有 执行此操作。

再一次,一个例子可以更好地解释 ^this。这就是我想要的样子:

<html>
    <body>
        <p>
            <span class="text">Go totally </span>
            <span class="post">kicks </span>
        </p>
        <p>
            <span class="text">hacks </span>
            <span class="post">its </span>
        </p>
        <p>
            <span class="text">debugger should </span>
            <span class="post">be </span>
        </p>
        <p>
            <span class="text">called </span>
            <span class="post">ogle</span>
        </p>
        <h3>
            <span class="statement">true</span>
        </h3>
    </body>
<html>

解决方案尝试

因为进一步区分 <h1> 标签和 <p> 标签会提供更多的解析选项,所以我想出了如何更改 <h1>class 属性] 标签:

<html>
    <body>
        <h1>
            <span class="title">Go </span>
        </h1>
        <p>
            <span class="text">totally </span>
            <span class="post">kicks </span>
        </p>
        <p>
            <span class="text">hacks </span>
            <span class="post">its </span>
        </p>
        <h1>
            <span class="title">debugger </span>
        </h1>
        <p>
            <span class="text">should </span>
            <span class="post">be </span>
        </p>
        <p>
            <span class="text">called </span>
            <span class="post">ogle </span>
        </p>
        <h3>
            <span class="statement">true</span>
        </h3>
    </body>
<html>

使用此代码:

html_code := strings.NewReader(`
code_example_above
`)
doc, _ := goquery.NewDocumentFromReader(html_code)
doc.Find("h1").Each(func(i int, s *goquery.Selection) {
    s.SetAttr("class", "title")
    class, _ := s.Attr("class")
    if class == "title" {
        fmt.Println(class, s.Text())
    }
})

我知道我可以 select <p..."text"<h1..."title" 之后 doc.Find("h1+p") s.Next()doc.Find("h1").Each 函数内:

doc.Find("h1").Each(func(i int, s *goquery.Selection) {
    s.SetAttr("class", "title")
    class, _ := s.Attr("class")
    if class == "title" {
        fmt.Println(class, s.Text())
        fmt.Println(s.Next().Text())
    }
})

我不知道如何插入从 <h1..."title"<p..."text" 的文本。我已经尝试使用 s.After()s.Before()s.Append() 的多种变体,例如:

doc.Find("h1").Each(func(i int, s *goquery.Selection) {
    s.SetAttr("class", "title")
    class, _ := s.Attr("class")
    if class == "title" {
        s.After(s.Text())
        fmt.Println(s.Next().Text())
    }
})

但我不知道如何做我想做的事。

如果我改用 s.After(s.Next().Text()),我会得到这个错误输出:

panic: expected identifier, found 5 instead

goroutine 1 [running]:
code.google.com/p/cascadia.MustCompile(0xc2082f09a0, 0x62, 0x62)
    /home/*/go/src/code.google.com/p/cascadia/selector.go:59 +0x77
github.com/PuerkitoBio/goquery.(*Selection).After(0xc2082ea630, 0xc2082f09a0, 0x62, 0x5)
    /home/*/go/src/github.com/PuerkitoBio/goquery/manipulation.go:18 +0x32
main.func·001(0x0, 0xc2082ea630)
    /home/*/go/test2.go:78 +0x106
github.com/PuerkitoBio/goquery.(*Selection).Each(0xc2082ea600, 0x7cb678, 0x2)
    /home/*/go/src/github.com/PuerkitoBio/goquery/iteration.go:7 +0x173
main.ExampleScrape()
    /home/*/go/test2.go:82 +0x213
main.main()
    /home/*/go/test2.go:175 +0x1b

goroutine 9 [runnable]:
net/http.(*persistConn).readLoop(0xc208047ef0)
    /usr/lib/go/src/net/http/transport.go:928 +0x9ce
created by net/http.(*Transport).dialConn
    /usr/lib/go/src/net/http/transport.go:660 +0xc9f

goroutine 17 [syscall, locked to thread]:
runtime.goexit()
    /usr/lib/go/src/runtime/asm_amd64.s:2232 +0x1

goroutine 10 [select]:
net/http.(*persistConn).writeLoop(0xc208047ef0)
    /usr/lib/go/src/net/http/transport.go:945 +0x41d
created by net/http.(*Transport).dialConn
    /usr/lib/go/src/net/http/transport.go:661 +0xcbc
exit status 2

(我的脚本的行与上面示例的行不匹配,但是我的脚本的 "line 72" 包含代码 s.After(s.Next().Text())。我不知道具体是什么 panic: expected identifier, found 5 instead 表示。)

总结

总而言之,我的问题是我不太清楚如何使用 goquery 向标签添加文本。

我想我很接近。有地鼠绝地武士能够并愿意帮助这个学徒吗?

类似这段代码的工作,它找到所有 <h1> 个节点,然后找到这些 <h1> 个节点内的所有 <span> 个节点,寻找 class text。然后它获取 <h1> 节点的下一个元素,如果它是一个 <p>,里面有一个 <span>,那么它将最后一个 <span> 替换为一个新的 <span> 与新文本并删除 <h1>.

我想知道是否可以使用 goquery 创建节点而无需编写 html...

package main

import (
    "fmt"
    "strings"

    "github.com/PuerkitoBio/goquery"
)

var htmlCode string = `<html>
...
<html>`

func main() {
    doc, _ := goquery.NewDocumentFromReader(strings.NewReader((htmlCode)))
    doc.Find("h1").Each(func(i int, h1 *goquery.Selection) {
        h1.Find("span").Each(func(j int, s *goquery.Selection) {
            if s.HasClass("text") {
                if p := h1.Next(); p != nil {
                    if ps := p.Children().First(); ps != nil && ps.HasClass("text") {
                        ps.ReplaceWithHtml(
                            fmt.Sprintf("<span class=\"text\">%s%s</span>)", s.Text(), ps.Text()))
                        h1.Remove()
                    }
                }
            }
        })
    })
    htmlResult, _ := doc.Html()
    fmt.Println(htmlResult)
}