美文网首页
go小项目-html解析

go小项目-html解析

作者: c4a1d989518e | 来源:发表于2018-03-15 11:30 被阅读53次

项目要求

解析一个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页面,用来测试,均可以测试通过,所以此段代码是经过测试的代码。

参考链接

https://github.com/gophercises/link/tree/solution

相关文章

网友评论

      本文标题:go小项目-html解析

      本文链接:https://www.haomeiwen.com/subject/irofqftx.html