golang HTML节点树遍历与处理插件库htree的使用

Golang HTML节点树遍历与处理插件库htree的使用

Htree是一个用于遍历、导航、筛选和处理html.Node对象树的Go包。

基本用法

以下是一个使用htree包处理HTML节点的完整示例demo:

package main

import (
	"fmt"
	"golang.org/x/net/html"
	"golang.org/x/net/html/atom"
	"github.com/bobg/htree/v2"
	"strings"
)

func main() {
	// 示例HTML字符串
	htmlStr := `
	<!DOCTYPE html>
	<html>
	<head>
		<title>Test Page</title>
	</head>
	<body>
		<div class="content">
			<h1>Hello World</h1>
			<p>This is a paragraph</p>
			<div id="footer" class="content-footer">
				<span>Copyright 2023</span>
			</div>
		</div>
	</body>
	</html>
	`

	// 解析HTML
	root, err := html.Parse(strings.NewReader(htmlStr))
	if err != nil {
		panic(err)
	}

	// 查找body元素
	body := htree.FindEl(root, func(n *html.Node) bool {
		return n.DataAtom == atom.Body
	})

	if body == nil {
		panic("body element not found")
	}

	// 查找带有content类的div元素
	contentDiv := htree.FindEl(body, func(n *html.Node) bool {
		return n.DataAtom == atom.Div && htree.ElClassContains(n, "content")
	})

	if contentDiv != nil {
		// 打印content div的内容
		fmt.Println("Content Div found:")
		for child := contentDiv.FirstChild; child != nil; child = child.NextSibling {
			if child.Type == html.ElementNode {
				fmt.Printf("- %s: %s\n", child.Data, htree.TextContent(child))
			}
		}
	}

	// 查找页脚元素
	footer := htree.FindEl(contentDiv, func(n *html.Node) bool {
		return n.DataAtom == atom.Div && htree.ElClassContains(n, "content-footer")
	})

	if footer != nil {
		fmt.Println("\nFooter text:", htree.TextContent(footer))
	}
}

主要功能

htree包提供了以下主要功能:

  1. 查找元素:使用FindEl函数在节点树中查找匹配条件的元素

  2. 类名检查:使用ElClassContains检查元素是否包含特定类名

  3. 文本内容提取:使用TextContent获取元素及其子元素的文本内容

示例输出

运行上述代码将输出:

Content Div found:
- h1: Hello World
- p: This is a paragraph
- div: Copyright 2023

Footer text: Copyright 2023

htree包简化了HTML节点树的遍历和处理,特别适合需要从HTML文档中提取特定内容的场景。


更多关于golang HTML节点树遍历与处理插件库htree的使用的实战教程也可以访问 https://www.itying.com/category-94-b0.html

1 回复

更多关于golang HTML节点树遍历与处理插件库htree的使用的实战系列教程也可以访问 https://www.itying.com/category-94-b0.html


Golang HTML节点树遍历与处理:htree库使用指南

htree是一个轻量级的Go语言HTML解析和操作库,它提供了一种简单高效的方式来遍历和处理HTML文档树。下面我将详细介绍htree的使用方法。

安装htree

首先安装htree库:

go get github.com/andybalholm/htree

基本用法

解析HTML文档

package main

import (
	"fmt"
	"github.com/andybalholm/htree"
	"strings"
)

func main() {
	html := `
	<html>
		<body>
			<div id="content">
				<p>Hello, World!</p>
				<ul>
					<li>Item 1</li>
					<li>Item 2</li>
				</ul>
			</div>
		</body>
	</html>
	`

	// 解析HTML
	doc, err := htree.Parse(strings.NewReader(html))
	if err != nil {
		panic(err)
	}
	
	// 处理文档...
}

遍历节点树

htree提供了多种遍历节点树的方法:

// 深度优先遍历
func traverseDFS(n *htree.Node) {
	fmt.Println("Node:", n.Data)
	for c := n.FirstChild; c != nil; c = c.NextSibling {
		traverseDFS(c)
	}
}

// 查找特定元素
func findElements(doc *htree.Node, tagName string) []*htree.Node {
	var result []*htree.Node
	var traverse func(*htree.Node)
	
	traverse = func(n *htree.Node) {
		if n.Type == htree.ElementNode && n.Data == tagName {
			result = append(result, n)
		}
		for c := n.FirstChild; c != nil; c = c.NextSibling {
			traverse(c)
		}
	}
	
	traverse(doc)
	return result
}

// 使用示例
divs := findElements(doc, "div")
for _, div := range divs {
	fmt.Println("Found div:", div)
}

操作节点

// 获取元素属性
func getAttribute(n *htree.Node, attrName string) string {
	for _, attr := range n.Attr {
		if attr.Key == attrName {
			return attr.Val
		}
	}
	return ""
}

// 修改元素内容
func setTextContent(n *htree.Node, text string) {
	// 移除所有子节点
	for n.FirstChild != nil {
		n.RemoveChild(n.FirstChild)
	}
	// 添加文本节点
	n.AppendChild(&htree.Node{
		Type: htree.TextNode,
		Data: text,
	})
}

// 添加新元素
func addListItem(ul *htree.Node, text string) {
	li := &htree.Node{
		Type: htree.ElementNode,
		Data: "li",
	}
	li.AppendChild(&htree.Node{
		Type: htree.TextNode,
		Data: text,
	})
	ul.AppendChild(li)
}

高级功能

CSS选择器查询

htree支持类似jQuery的CSS选择器查询:

import "github.com/andybalholm/htree/query"

func main() {
	// ...解析文档代码...
	
	// 使用CSS选择器查找元素
	items := query.Find(doc, "ul li")
	for _, item := range items {
		fmt.Println("List item:", item.FirstChild.Data)
	}
	
	// 查找ID为content的div
	contentDiv := query.FindOne(doc, "div#content")
	if contentDiv != nil {
		fmt.Println("Content div found")
	}
}

修改和生成HTML

// 修改文档后生成HTML字符串
func modifyAndOutput(doc *htree.Node) string {
	// 找到第一个p标签并修改内容
	p := query.FindOne(doc, "p")
	if p != nil {
		setTextContent(p, "Modified content")
	}
	
	// 添加新的列表项
	ul := query.FindOne(doc, "ul")
	if ul != nil {
		addListItem(ul, "Item 3")
	}
	
	// 生成HTML字符串
	var buf bytes.Buffer
	htree.Render(&buf, doc)
	return buf.String()
}

实际应用示例

下面是一个完整的示例,演示如何解析HTML,修改内容并输出结果:

package main

import (
	"bytes"
	"fmt"
	"github.com/andybalholm/htree"
	"github.com/andybalholm/htree/query"
	"strings"
)

func main() {
	html := `
	<html>
		<head>
			<title>Test Page</title>
		</head>
		<body>
			<div id="content">
				<h1>Welcome</h1>
				<p>This is a test page.</p>
				<ul class="items">
					<li>First item</li>
					<li>Second item</li>
				</ul>
			</div>
		</body>
	</html>
	`

	// 解析HTML
	doc, err := htree.Parse(strings.NewReader(html))
	if err != nil {
		panic(err)
	}

	// 修改标题
	title := query.FindOne(doc, "title")
	if title != nil {
		title.FirstChild.Data = "Modified Title"
	}

	// 在列表中添加新项目
	ul := query.FindOne(doc, "ul.items")
	if ul != nil {
		newItem := &htree.Node{
			Type: htree.ElementNode,
			Data: "li",
		}
		newItem.AppendChild(&htree.Node{
			Type: htree.TextNode,
			Data: "Third item",
		})
		ul.AppendChild(newItem)
	}

	// 输出修改后的HTML
	var buf bytes.Buffer
	htree.Render(&buf, doc)
	fmt.Println(buf.String())
}

htree是一个功能强大但轻量级的HTML处理库,非常适合需要解析和操作HTML文档的Go应用程序。它比标准库的html包提供了更多的便利方法,同时保持了高性能和低内存占用。

回到顶部