项目要求
解析一个html页面,将其中的href标签中的链接地址和href标签所包裹的content内容,组成一个字典,打印出来
如下图
实现效果
项目代码
上面的图片是如下代码的运行结果。
package main
import (
"fmt"
"strings"
"github.com/gophercises/link"
)
var exampleHtml = `
<html>
<body>
<h1>Hello!</h1>
<a href="/other-page">
A link to another page
<span> some span </span>
</a>
<a href="/page-two">A link to a second page</a>
</body>
</html>
`
func main() {
r := strings.NewReader(exampleHtml)
links, err := link.Parse(r)
if err != nil {
panic(err)
}
fmt.Printf("%+v\n", links)
}
这段代码没有难点,主要是调用了一个link包,利用了其中的Parse函数。
link包的代码如下:
package link
import (
"io"
"strings"
"golang.org/x/net/html"
)
// Link represents a link (<a href="...">) in an HTML
// document.
type Link struct {
Href string
Text string
}
// Parse will take in an HTML document and will return a
// slice of links parsed from it.
func Parse(r io.Reader) ([]Link, error) {
doc, err := html.Parse(r)
if err != nil {
return nil, err
}
nodes := linkNodes(doc)
var links []Link
for _, node := range nodes {
links = append(links, buildLink(node))
}
return links, nil
}
func buildLink(n *html.Node) Link {
var ret Link
for _, attr := range n.Attr {
if attr.Key == "href" {
ret.Href = attr.Val
break
}
}
ret.Text = text(n)
return ret
}
func text(n *html.Node) string {
if n.Type == html.TextNode {
return n.Data
}
if n.Type != html.ElementNode {
return ""
}
var ret string
for c := n.FirstChild; c != nil; c = c.NextSibling {
ret += text(c)
}
return strings.Join(strings.Fields(ret), " ")
}
func linkNodes(n *html.Node) []*html.Node {
if n.Type == html.ElementNode && n.Data == "a" {
return []*html.Node{n}
}
var ret []*html.Node
for c := n.FirstChild; c != nil; c = c.NextSibling {
ret = append(ret, linkNodes(c)...)
}
return ret
}
项目学习点
link包可以转换一下,用于其他html内容的提取,这个Parse函数具有一定的通用性,原来的github,给出了4个html页面,用来测试,均可以测试通过,所以此段代码是经过测试的代码。
网友评论