吾爱破解 - LCG - LSG |安卓破解|病毒分析|www.52pojie.cn

 找回密码
 注册[Register]

QQ登录

只需一步,快速开始

查看: 1454|回复: 6
上一主题 下一主题
收起左侧

[讨论] 解决golang chromedp 打开过多浏览器进程问题

[复制链接]
跳转到指定楼层
楼主
bobo2017365 发表于 2022-10-20 11:09 回帖奖励
本帖最后由 bobo2017365 于 2022-10-20 14:20 编辑

我写了一个爬虫,抽出了一个函数,专门用来打开浏览器的页面,获取文本内容

爬取了300多个页面之后,发现goland打开了几百个chrome进程,我猜是调用了一次公共函数之后,就重新打开了一个浏览器进程,该怎么改进呢?让程序只要检测到chrome进程是打开的,就利用已经有的进程

经过群友讨论和一番Google,在官方代码仓库issue里找到了解决办法

PS:官方开发者也是有些坑,没看到官网文档里有些退出的方法

[Golang] 纯文本查看 复制代码
package common

import (
        "context"
        "github.com/chromedp/cdproto/cdp"
        "github.com/chromedp/chromedp"
        "log"
        "time"
)

func GetHttpHtmlContent(url string, visibleEleId string, clickEle bool, headless bool) (string, error) {
        opts := append(chromedp.DefaultExecAllocatorOptions[:],
                chromedp.Flag("headless", headless),
        )

        c, concel_at_begin := chromedp.NewExecAllocator(context.Background(), opts...)   # 这里的变量concel_at_begin 一定不能省去
        // create context
        chromeCtx, cancel := chromedp.NewContext(c, chromedp.WithLogf(log.Printf))
        //  Execute an empty task,  Create in advance with Chrome example
        chromedp.Run(chromeCtx, make([]chromedp.Action, 0, 1)...)
        // Create a context , The timeout is 40s
        timeoutCtx, cancel := context.WithTimeout(chromeCtx, 20*time.Second)
        defer cancel()
        var htmlContent string
        var res []*cdp.Node
        chromedp.Run(chromeCtx,
                chromedp.Navigate(url),
                //chromedp.EvaluateAsDevTools(fmt.Sprintf(`document.querySelector("%v")`, visibleEleId), ""),
                chromedp.Nodes(visibleEleId, &res, chromedp.AtLeast(0)),
        )
        if len(res) != 0 {
                //fmt.Println("length res is not 0, find the element", res)
                if clickEle {
                        chromedp.Run(timeoutCtx,
                                chromedp.SendKeys(`select[id=selectT]`, "终"),
                                chromedp.Sleep(30*time.Second),
                                chromedp.OuterHTML(`body`, &htmlContent, chromedp.ByQuery),
                        )
                } else {
                        chromedp.Run(timeoutCtx,
                                chromedp.OuterHTML(`body`, &htmlContent, chromedp.ByQuery),
                        )
                }

        } else {
                //fmt.Println("length res is  0, not find the element")
                chromedp.Run(timeoutCtx,
                        chromedp.OuterHTML(`body`, &htmlContent, chromedp.ByQuery),
                )
        }
        concel_at_begin()   # 在这里添加这一句, 程序会在这里自动关闭浏览器
        return htmlContent, nil
}

发帖前要善用论坛搜索功能,那里可能会有你要找的答案或者已经有人发布过相同内容了,请勿重复发帖。

沙发
fjqisba 发表于 2022-10-20 11:33
NewExecAllocator,这个函数貌似执行一次就行了?

免费评分

参与人数 1吾爱币 +1 收起 理由
bobo2017365 + 1 热心回复!

查看全部评分

3#
lm93129 发表于 2022-10-20 11:39
GetHttpHtmlContent这个函数你每次调用的时候,都会打开一个chrome,你应该在这个函数里面使用一个close来关闭对应的chrome,或者将初始化chrome这件事情放在这个函数的外面,直接传入chromedp.Run到函数中处理相关事件。

免费评分

参与人数 1吾爱币 +1 收起 理由
bobo2017365 + 1 热心回复!

查看全部评分

4#
 楼主| bobo2017365 发表于 2022-10-20 12:14 |楼主
fjqisba 发表于 2022-10-20 11:33
NewExecAllocator,这个函数貌似执行一次就行了?

也许我要把打开浏览器进程这个函数再拆分

url 应该传给具体打开页面的动作就好了
5#
 楼主| bobo2017365 发表于 2022-10-20 12:15 |楼主
lm93129 发表于 2022-10-20 11:39
GetHttpHtmlContent这个函数你每次调用的时候,都会打开一个chrome,你应该在这个函数里面使用一个close来 ...

嗯,看到了官网的issue,说是可以用 cancel()在 函数结尾处,这样可以关闭浏览器进程
6#
nullable 发表于 2022-10-20 14:24
貌似有个 .stop() 用来停止当前开启的进程。或者直接拿到页码整数,用 for开循环后close() ?
7#
 楼主| bobo2017365 发表于 2022-10-20 14:40 |楼主
nullable 发表于 2022-10-20 14:24
貌似有个 .stop() 用来停止当前开启的进程。或者直接拿到页码整数,用 for开循环后close() ?

爬虫是爬取同一个网站的不同页面,所以没办法用for循环
您需要登录后才可以回帖 登录 | 注册[Register]

本版积分规则 警告:本版块禁止回复与主题无关非技术内容,违者重罚!

快速回复 收藏帖子 返回列表 搜索

RSS订阅|小黑屋|处罚记录|联系我们|吾爱破解 - LCG - LSG ( 京ICP备16042023号 | 京公网安备 11010502030087号 )

GMT+8, 2024-5-13 17:49

Powered by Discuz!

Copyright © 2001-2020, Tencent Cloud.

快速回复 返回顶部 返回列表