我正在尝试解析HTML页面并打印其链接。我正在遍历解析的HTML树,以递归方式将链接添加到一片字符串中。当我收到内存不足错误
时,我缺少了一些东西这是我的代码:
package parser
import (
"errors"
"io"
"golang.org/x/net/html"
)
//URLParser returns all the urls inside a html page
type URLParser struct {
}
//GetURLS returns all
func (URLParser) GetURLS(htmlInput io.Reader) (*[]string, error) {
result := []string{}
htmlRoot, err := html.Parse(htmlInput)
//result := make([]string, 1000)
if err != nil {
parserError := errors.New("html parser failed with error" + err.Error())
return nil, parserError
}
finalResult := traverseHTMLTree(htmlRoot, &result)
return finalResult, nil
}
func traverseHTMLTree(node *html.Node, result *[]string) *[]string {
if node == nil {
return nil
}
if isLinkElement(node) {
currlink, shouldUse := getURLAttrb(node.Attr)
if shouldUse {
*result = append(*result, currlink)
}
}
for currNode := node.FirstChild; currNode != nil; currNode = currNode.NextSibling {
currRest := traverseHTMLTree(currNode, result)
if currRest != nil {
*result = append(*currRest, *result...)
}
}
return result
}
func getURLAttrb(attr []html.Attribute) (string, bool) {
for i := 0; i < len(attr); i++ {
if attr[i].Key == "href" {
return attr[i].Val, true
}
}
return "", false
}
func isLinkElement(node *html.Node) bool {
if node.Type == html.ElementNode {
if node.Data == "a" {
return true
}
}
return false
}
[仅尝试打印指向stdout的链接时,它可以完美地工作,所以它必须与我处理切片的方式有关。
对于HTML树中的每个节点,您将递归地将结果数组的内容添加到其自身。那应该增长很快。
注意,当您检查是否为isLinkElement
时,会将项目添加到结果列表中。
然后为html树的每个元素,将结果数组的内容附加到其自身,使其成倍增加。
您正在将指针传递给切片。您实际上在整个程序中使用了一个切片,并不断添加其中。您从traverseHTMLTree返回的内容是同一切片,而不是其副本。因此,它一直在增长。
解决它的一种方法是:不要将指针传递给切片。传递当前切片,对其进行更新,然后返回新切片。