是的,抱歉标题没有解释。我需要使用一个例子。
这是我发布的另一个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>
我想:
<h1..."text"
的内容。 <p..."text"
的内容中。 <p>
标记的<h1>
标记执行此操作。 <h1>
标记的所有执行此操作。 再一次,一个例子解释了^这更好。这就是我想要的样子:
<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吗?
答案 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)
}