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

时间:2015-01-07 20:39:57

标签: html go concatenation

是的,抱歉标题没有解释。我需要使用一个例子。

这是我发布的另一个question的延续,它解决了一个问题,但并非全部问题。我已将该问题的大部分背景信息都放入此问题中。此外,我只是在调查Go大约5天(我几个月前才开始学习代码),所以我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>

目标

我想:

  1. 提取 <h1..."text"的内容。
  2. 将此提取的内容(并连接)到<p..."text"的内容中。
  3. 仅针对{em>紧跟 <p>标记的<h1>标记执行此操作。
  4. 为页面上<h1>标记的所有执行此操作。
  5. 再一次,一个例子解释了^这更好。这就是我想要的样子:

    <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>标记的进一步区分会提供更多解析选项,因此我已经弄明白了如何更改class <h1>属性}标签:

    <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())
        }
    })
    

    我知道我可以在<p..."text"之后选择<h1..."title" <{em> 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
    

    (我的脚本行与上面示例的行不匹配,但是&#34;我的脚本的第72行和第34行包含代码s.After(s.Next().Text())。我不知道知道panic: expected identifier, found 5 instead究竟是什么意思。)

    摘要

    总之,我的问题是,我无法完全理解如何使用goquery向标记添加文字。

    我想我已经接近了。任何地鼠Jedis都能够并愿意帮助这个padawan吗?

1 个答案:

答案 0 :(得分:3)

像这样的代码完成工作,它找到所有<h1>个节点,然后查找这些<span>节点内的所有<h1>个节点,寻找类text的节点。然后,它获取<h1>节点的下一个元素(如果它是<p>,在<span>内),然后用新<span>替换最后<span> 1}}使用新文本并删除<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)
}