问题内容 我面临的问题是,即使仅尝试 200 个请求也会导致程序占用容器的 6gb 内存并最终被 oom 杀死。 我的想法是提取 html 中存在的所有文本节点,然后处理它们以提取它们
我面临的问题是,即使仅尝试 200 个请求也会导致程序占用容器的 6gb 内存并最终被 oom 杀死。 我的想法是提取 html 中存在的所有文本节点,然后处理它们以提取它们的名称、该标签的 html 和文本。因此,为了生成特定标签的 html,我使用 golang.org/x/net/html 中的 render 函数。其中我提供 strings.builder 作为 io.writer 来编写生成的 html。但由于某种原因,构建器占用了太多内存。
package main
import (
"encoding/csv"
"io"
"log"
"net/Http"
"strings"
"Golang.org/x/net/html"
)
func main() {
mux := http.NewServeMux()
mux.HandleFunc("/data", GetData)
if err := http.ListenAndServe(":8001", mux); err != nil {
log.Println(err)
}
}
type TagInfo struct {
Tag string
Name string
Text string
}
// http.handler
func GetData(w http.ResponseWriter, r *http.Request) {
u := r.URL.Query().Get("url")
doc, err := GetDoc(u)
if err != nil {
log.Println(err)
w.WriteHeader(500)
return
}
var buf strings.Builder
data := Extract(doc, &buf)
csvw := csv.NewWriter(io.Discard)
for _, d := range data {
csvw.Write([]string{d.Name, d.Tag, d.Text})
}
}
// fires request and get text/html
func GetDoc(u string) (*html.node, error) {
res, err := http.Get(u)
if err != nil {
return nil, err
}
defer res.Body.Close()
return html.Parse(res.Body)
}
func Extract(doc *html.Node, buf *strings.Builder) []TagInfo {
var (
tags = make([]TagInfo, 0, 100)
f func(*html.Node)
)
f = func(n *html.Node) {
if n.Type == html.TextNode {
text := strings.TrimSpace(n.Data)
if text != "" {
parent := n.Parent
tag := Render(parent, buf)
tagInfo := TagInfo{
Tag: tag,
Name: parent.Data,
Text: n.Data,
}
tags = append(tags, tagInfo)
}
}
for child := n.FirstChild; child != nil; child = child.NextSibling {
f(child)
}
}
f(doc)
return tags
}
// Render the html around the tag
// if node is text then pass the
// parent node paramter in function
func Render(n *html.Node, buf *strings.Builder) string {
defer buf.Reset()
if err := html.Render(buf, n); err != nil {
log.Println(err)
return ""
}
return buf.String()
}
如果您想要特定的网址列表,这里就是。我一次发出了大约 60 个请求。
我尝试使用 bytes.buffer bytes.buffer
和 sync.pool
但两者都有相同的问题。使用 pprof
我注意到 strings.builder 的 writestring
方法导致大量内存使用。
所以这里的基本问题是接受任何 content-type
,这在抓取方面是不可接受的,大多数网站都需要发送 text/html
。
问题是即使url发送任何不代表html数据的内容golang.org/x/net/html
仍然接受它而不抛出错误。
让我们举一个例子,其中返回 application/pdf
,然后正文将包含 html.Parse
解析的 pdf 的二进制数据,并且不会返回任何错误,这是用于抓取/爬行接受二进制数据的奇怪行为思维库。
解决方案是:检查响应头,如果只有数据是html,然后继续,否则会出现歧义或更高的内存使用量(可能更低),但我们无法预测会发生什么发生。
以上就是html 渲染函数内存泄漏的详细内容,更多请关注编程网其它相关文章!
--结束END--
本文标题: html 渲染函数内存泄漏
本文链接: https://lsjlt.com/news/561442.html(转载时请注明来源链接)
有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341
2024-05-24
2024-05-24
2024-05-24
2024-05-24
2024-05-24
2024-05-24
2024-05-24
2024-05-24
2024-05-24
2024-05-24
回答
回答
回答
回答
回答
回答
回答
回答
回答
回答
0