V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
The Go Programming Language
http://golang.org/
Go Playground
Go Projects
Revel Web Framework
ysmood
V2EX  ›  Go 编程语言

Rod 一个为简化自动化和爬虫设计的 devtools driver

  •  3
     
  •   ysmood ·
    ysmood · 2020-07-02 19:12:41 +08:00 · 12360 次点击
    这是一个创建于 1584 天前的主题,其中的信息可能已经有所发展或是发生改变。

    项目地址: https://github.com/ysmood/rod

    这个库的主要原理就是利用浏览器的 devtools 可编程接口来操控浏览器。日常你可以用它自动化一些重复的页面任务,相比油猴子有更多的高级功能和 golang 强大的生态。工作上可以用它辅助集成化测试减少人力消耗。开发上可以用它简化一些传统爬虫需要费很多时间逆向工程的场景。

    根目录的 readme 里有常见的问答,以及和 chromedp,puppeteer 等库的比较。

    同类的项目有 chromedp,但是其存在架构设计上的问题且更新缓慢,所以我们开发了 rod,感兴趣的朋友请来试试。欢迎对自动化有兴趣的朋友加入到项目中来,这是我们的聊天室: https://discord.gg/PAaMGJw

    因为问的人特别多,我们列了个表格用实际可运行的例子帮助大家直观对比 rod 和 chromedp: https://github.com/go-rod/rod/tree/master/lib/examples/compare-chromedp

    下面是一个打印 awesome-go 某一类别项目列表的例子:

    package main
    
    import (
        "log"
    
        "github.com/go-rod/rod"
    )
    
    func main() {
        // 启动一个浏览器并新建一个页面
        page := rod.New().Connect().Page("https://github.com/avelino/awesome-go")
    
        // 获取页面里含有 "Selenium and browser control tools" 标题的下方元素
        // 这里我们将获取到 p 标签下方的列表
        section := page.ElementMatches("p", "Selenium and browser control tools").Next()
    
        // 在列表里获取全部 li 标签
        projects := section.Elements("li")
    
        for _, project := range projects {
            // 从 li 标签里获取 a 标签
            link := project.Element("a")
            
            // 打印 a 里的文字,a 的链接,以及 li 里的文字
            log.Println(
                link.Text(),
                link.Property("href"),
                project.Text(),
            )
        }
    }
    
    66 条回复    2023-05-26 15:39:58 +08:00
    porr
        1
    porr  
       2020-07-02 19:18:36 +08:00
    试试看能不能用来批量取消微博收藏。
    ysmood
        2
    ysmood  
    OP
       2020-07-02 19:26:32 +08:00
    @porr 你可以看下这个例子 https://github.com/go-rod/rod/blob/9295ca9ae9570da05ef5d1fd34059c8f790630ec/examples_test.go#L43-L63

    用 launcher.NewUserMode() 来复用你的微博登陆信息,你就可以免登陆直接去操作相关任务了。
    0o0O0o0O0o
        3
    0o0O0o0O0o  
       2020-07-02 19:40:01 +08:00
    go 版的 puppeteer ?
    ysmood
        4
    ysmood  
    OP
       2020-07-02 19:53:22 +08:00
    @0o0O0o0O0o 是的,功能正在接近 puppeteer,甚至在某些方面已经有更多高级功能。
    iiusky
        5
    iiusky  
       2020-07-02 19:56:37 +08:00 via Android
    可以执行 js 么?模拟点击
    ysmood
        6
    ysmood  
    OP
       2020-07-02 19:58:59 +08:00
    @iiusky 可以。可以移步 https://github.com/go-rod/rod/tree/master/lib/examples/compare-chromedp

    第一个就是点击的例子,eval 的例子也有
    tikazyq
        7
    tikazyq  
       2020-07-02 20:05:39 +08:00 via iPhone
    不错,试用下,如果可以的话看如何集成到 crawlab
    ysmood
        8
    ysmood  
    OP
       2020-07-02 20:16:42 +08:00
    @tikazyq 欢迎合作,有任何问题都可以来群里侃侃 https://discord.gg/PAaMGJw
    supermoonie
        9
    supermoonie  
       2020-07-02 20:20:04 +08:00 via iPhone
    已经用 java 写过一遍了🤪,就一个 websocket 🤪,本来还打算用 c++再写一遍,写了一半放弃了🤪
    iiusky
        10
    iiusky  
       2020-07-02 23:52:02 +08:00 via Android
    回头试试看,
    ysmood
        11
    ysmood  
    OP
       2020-07-03 11:26:40 +08:00
    @iiusky 可以看下这个 V2EX 的每日自动签到例子 https://github.com/go-rod/v2ex-clockin
    huyinjie
        12
    huyinjie  
       2020-07-03 14:31:36 +08:00 via iPhone
    支持
    ysmood
        13
    ysmood  
    OP
       2020-07-03 14:51:35 +08:00
    @huyinjie 多谢支持~
    locoz
        14
    locoz  
       2020-07-03 19:23:15 +08:00
    有意思,收藏放着
    xinyana
        15
    xinyana  
       2020-07-04 10:27:06 +08:00 via Android
    作者你好,可以实现 iMacros 的部分自动化功能吗
    ysmood
        16
    ysmood  
    OP
       2020-07-04 11:41:36 +08:00 via Android
    @xinyana 市场上继续 selenium 的工具太多了,老实说我没有用过 iMacros, 稍微看了下他们的说明,见解可能有偏颇望见谅,如果只是 chrome 的话,理论上 rod 功能是要比它更多更可控,关于这点可以参考我们 readme 里的和 selenium 的比较,但缺点是 rod 更底层。社区里有个朋友正在基于 rod 开发类 iMacros 的工具,有兴趣可以去看看 https://github.com/go-rod/wayang
    ysmood
        17
    ysmood  
    OP
       2020-07-04 11:42:17 +08:00 via Android
    更正 继续 为 基于
    xinyana
        18
    xinyana  
       2020-07-05 04:13:19 +08:00 via Android
    @ysmood 谢谢精心答复,我看好明天研究一下,就是想实现自动批量打印单据,在用一个 web 版 erp 特别不友好,打印麻烦
    vus520
        19
    vus520  
       2020-07-06 14:23:17 +08:00
    用于爬虫业务,可以不渲染图片么
    ysmood
        20
    ysmood  
    OP
       2020-07-06 15:18:34 +08:00
    @vus520 当然,默认就是不渲染图片。rod 使用的 headless 技术,这个你可以查阅相关文章,非常多。当然 rod 的性能肯定比 scrapy 之类的在理论上就差很多,但 rod 能做很多 scrapy 完全无法完成的复杂任务,且对爬虫的初学者更友好。
    vus520
        21
    vus520  
       2020-07-06 15:24:20 +08:00
    @ysmood 静态页面我用 scrapy,动态页面我使用 splash 这类渲染器,想找一个性能比 splash 更好的方案。
    ysmood
        22
    ysmood  
    OP
       2020-07-06 16:05:58 +08:00
    @vus520 那我推荐你试试 rod,splash 基于 QT, 它用的 webkit 和 v8,rod 基于 chromium,它用的 blink 和 v8,blink 是 fork 的 webkit,他们团队对此的解释可以看这里 http://www.chromium.org/blink/developer-faq

    chrome 团队在这篇文章里说了:我们会有更好的多线程支持和性能提升。当然这点就仁者见仁智者见智了。我个人的观察是用 rod 内存消耗基本是几 MB,cpu 的消耗更大的是在于我渲染的什么网站,而不是选什么引擎。关注问题我们看瓶颈在哪,所以我发现容不容易开发才是我选择使用什么方案的决定性因素。比如如果我要实现个拖拽模拟,结果 webkit 要 hack 一堆函数,那我肯定是不会选 webkit 的。

    如果吹毛求疵的话,rod 是基于 golang 的,splash 是基于 python,单从你自己项目的架构和可维护性来讲,golang 往往是爬虫更佳的选择。python 之所以现在还在爬虫界这么火,我觉得还是因为老一辈的积累和工具的成熟度,但仅我个人来看未来还是 golang 更适合处理这方面的业务。
    ysmood
        23
    ysmood  
    OP
       2020-07-06 16:07:52 +08:00
    “cpu 的消耗” 订正为 “内存和 CPU 的消耗”
    vus520
        24
    vus520  
       2020-07-06 16:12:36 +08:00
    @ysmood 好的,我会做一个性能基准测试,感谢。
    ysmood
        25
    ysmood  
    OP
       2020-07-06 16:17:41 +08:00
    @vus520 如果能把你的结果分享出来那就好了,简单的开个 issue 我们就能看到,这样能帮助更多的人选择哪种方案更符合他们的需求。
    Te11UA
        26
    Te11UA  
       2020-07-06 16:22:25 +08:00
    作为爬虫我比较关心这个 issue 会不会在 Rod 上得到解决?大概意思是新开的 Tab 无法绕过反爬识别

    https://github.com/chromedp/chromedp/issues/557
    ysmood
        27
    ysmood  
    OP
       2020-07-06 16:27:26 +08:00
    @Te11UA 这个 rod 已经有解决方案了,如果你想了解更多反爬虫经验,可以去聊天群找 PiuPiuPiu,他正在做相关的开发,这里就不聊敏感话题了。
    vus520
        28
    vus520  
       2020-07-06 17:42:07 +08:00
    @vus520 没有问题,乐观估计应该会比 splash 好一点
    darrh00
        29
    darrh00  
       2020-07-06 18:57:35 +08:00
    >> Debugging friendly, auto input tracing, remote monitoring headless browser

    关于如何调试,有入门的帮助文档吗?
    xinyana
        30
    xinyana  
       2020-07-06 19:41:36 +08:00
    门槛有点高啊,零基础 **helloword**给个吧
    ysmood
        31
    ysmood  
    OP
       2020-07-06 20:04:03 +08:00   ❤️ 1
    @darrh00 有详尽的文档,上 go 的官方网站就能看,readme 里 examples 就是很容易找到才对:

    https://user-images.githubusercontent.com/1415488/86591222-184aa480-bfcc-11ea-8614-b7b2681b00b0.png
    ysmood
        32
    ysmood  
    OP
       2020-07-06 20:10:47 +08:00
    @xinyana readme 的 examples 里 第一个就是 hello world,我给不会 golang 的 QA 看,她都能猜到怎么用 rod:

    https://user-images.githubusercontent.com/1415488/86591430-8e4f0b80-bfcc-11ea-87a2-20245f5743e6.png

    要是你还觉得难,那你得先学习下 css selector 和爬虫相关的基础之时了
    guanzhangzhang
        34
    guanzhangzhang  
       2020-07-07 00:14:51 +08:00 via Android
    大佬带带我
    ysmood
        35
    ysmood  
    OP
       2020-07-07 02:06:54 +08:00
    @guanzhangzhang 不是什么大佬,你有问题,可以随时去聊天群里问,如果去英文的群,那能回答你的人就更多。觉得问题有一般性,可以提 issue 。能来贡献代码的人,我都会尽量帮你提高的。

    我来这里宣传是希望更多的人来维护,而不是来求夸奖求 star 的,那都是浮云。贡献者多了,我也能从大家的代码受益。
    tremblingblue
        36
    tremblingblue  
       2020-07-08 11:53:45 +08:00
    说个和项目无关的,项目名字让我想起了一个北欧乐队的专辑名字.
    missdeer
        37
    missdeer  
       2020-07-08 12:03:02 +08:00
    discord 劝退,微信或者 tg 多好,再不行 slack 嘛
    ysmood
        38
    ysmood  
    OP
       2020-07-08 13:23:36 +08:00
    @tremblingblue 比如 rod 作为人名还是非常常见的,就跟 jack 类似。
    Jirajine
        39
    Jirajine  
       2020-07-08 13:27:03 +08:00 via Android
    爬虫还是动态语言写起来更合适吧。
    ysmood
        40
    ysmood  
    OP
       2020-07-08 13:27:15 +08:00
    @missdeer 我们通过很多讨论过之后决定用 discord 的,tg 很难用,连代码高亮都没有。slack 我工作每天用,感觉对开源社区不太友好,更适合闭源项目,免费版还各种限制。

    好奇为什么 discord 劝退呢?能详细聊下吗?
    ysmood
        41
    ysmood  
    OP
       2020-07-08 13:38:45 +08:00
    @Jirajine 看场景吧,没有最好的,只有合不合适需求。如果项目复杂或者需要多人合作可能有类型会更方便,我觉得道理和为什么 javascript 的大量开发者转为 typescript 是一样的。

    而且写 golang 感觉和写脚本也没太大差别,大部分类型都可以省略。有了 IDE 辅助,反而比脚本语言完成同样的任务花的时间更少,也更少需要去看文档了。
    missdeer
        42
    missdeer  
       2020-07-08 17:37:59 +08:00
    @ysmood 不想再多一个聊天软件啊
    ysmood
        43
    ysmood  
    OP
       2020-07-08 19:58:40 +08:00
    @missdeer 我从来都不安装软件啊,打开页面就能用,discord 的网页版比 tg 的网页版好用太多了。
    WilliamYang
        44
    WilliamYang  
       2020-07-09 13:05:23 +08:00 via iPhone
    关注,对这个项目很有兴趣
    ysmood
        45
    ysmood  
    OP
       2020-07-09 20:42:53 +08:00
    @WilliamYang 欢迎来提需求或贡献代码~
    tinytin
        46
    tinytin  
       2020-07-10 01:40:32 +08:00 via iPhone
    支持👏
    ysmood
        47
    ysmood  
    OP
       2020-07-10 13:22:53 +08:00 via Android
    @tinytin 多谢支持
    iyaozhen
        48
    iyaozhen  
       2020-07-11 16:25:11 +08:00
    关于 selenium 这部分不太同意
    “It's slower by design because it encourages the use of hard-coded sleep.”

    这个没有哪里说要使用 sleep,自带的就有很多 wait 方法(比如官方例子 https://www.selenium.dev/documentation/en/),虽然没有内置 ajax 请求等待,但扩展一下就行了
    而且也支持 headless 模式运行

    只是说 selenium 走的 webdriver 这条路子没有 devtools 那么时髦,但事实上两条路都在持续发展

    应该说是 selenium 更侧重 web UI 自动化测试
    ysmood
        49
    ysmood  
    OP
       2020-07-11 18:54:58 +08:00
    @iyaozhen 是的。这段是很早期写的,用词有些过分了。我这就去修改下。我觉的 selenium 主要问题还是它基于 webdriver 协议 https://www.w3.org/TR/webdriver1/。这个协议的主要问题是还太早期,很多功能上的支持和 devtools 协议比起来还是太弱了,我还没研究 webdriver2,说不定会好些。比如你提到的劫持 ajax,webdriver1 根本就不支持,比如你要劫持 https 的请求时,webdriver1 只能借助代理,还要处理一堆证书问题,我恐怕你很难找个现成好用的插件(反正我是没找到 golang 和 java 的,只看到个 python 的 selenium-wire 但它还有限制)。你觉得这说服不了你,那对于 shadow-dom,webdriver1 就根本无法处理了。

    如果你看下这个 https://github.com/sukgu/shadow-automation-selenium/issues/7#issuecomment-563062460
    你就会知道这是质的差别,selenium 是无法处理 closed shadow root 的,然而 rod 可以。还有很多本质差别,日后有时间我们会尽量列个表出来。
    ysmood
        50
    ysmood  
    OP
       2020-07-11 19:19:18 +08:00
    @iyaozhen 说白了就是两个协议间的抗衡,目前来看由于 puppeteer 的广泛接受度,以及微软也加入到 chromium 阵营,恐怕留给 webdriver 的时间就不多了。

    我刚看了下 webdriver2,比起 1,就加了一点功能而已,还是太鸡肋了。举个简单的例子,你说 selenium 更侧重自动化测试,测试需要 profiling 的时候检测性能的时候,selenium 就得使用及其 hack 的手段了,而且也没发支持 devtools 那样丰富的功能。

    总体来说 webdriver 协议理想是非常好的但是相比 devtools 协议的成熟度,还是差太远了。关键是 firefox 都已经意识到这点在与 puppeteer 团队合作开发 devtools 的支持了,可见一斑。我当然是希望能用统一的协议,但现实就是这么骨感。
    iyaozhen
        51
    iyaozhen  
       2020-07-11 20:23:50 +08:00
    @ysmood 嗯 我知道。应该说是 selenium 唯一的优势就是多浏览器支持了,IE 、Safari 。自动化测试还是需要的。但已经很有局限性,优势也越来越不重要了(很多系统都是 chrome only )

    webdriver 一直也在更新(也是浏览器厂商支持,chrome 每版都有更新)但确实是昨日黄花了。

    还是那句话没有银弹,传统的自动化功能测试(代替手工回归),devtools 没有比 webdriver 明显的优势,有些奇怪的页面还是不稳定。

    当然绝大部分场景来说肯定还是首选 devtools,我的意思是可以更客观的对比下场景差异(也不用搞个细节技术点的列表)
    ysmood
        52
    ysmood  
    OP
       2020-07-14 00:14:56 +08:00
    @iyaozhen 更新了文档,把不正的描述去掉了,欢迎来指点。

    关于 chrome only 这个观点,我补充下。随着旧浏览器的淘汰,如今都用 react vue 之类的框架开发网页,跨浏览器支持已经不再是自动化测试的重点了,单测也往往不用 headless 这么重的东西,单测就够了,用了 headless 大概率就是集成测了,集成测试往往目标是冒烟保障,比如监测关键功能是否异常,浏览器兼容性这种细枝末节基本不是瓶颈所在。
    iyaozhen
        53
    iyaozhen  
       2020-07-14 01:53:00 +08:00
    @ysmood 赞 现在描述好很多了

    求同存异,大家观点差不多

    可惜团队技术栈不是 go,不然可以用用你的。祝项目越来越好
    iyaozhen
        54
    iyaozhen  
       2020-07-14 01:59:11 +08:00
    @ysmood 我擦,说了几天没注意看 ID,学长好
    ysmood
        55
    ysmood  
    OP
       2020-07-14 02:11:54 +08:00
    @iyaozhen 多谢。世界就是这么小呢。不是 Go 也没事,偶尔尝试下别的东西也不坏。我们 QA 也不会 Go,几天就能自己用 rod 写测试保障功能了。
    abc0707
        56
    abc0707  
       2020-07-24 17:57:49 +08:00
    请问 反反爬怎么做

    go browser.EachEvent(func(e *proto.TargetTargetCreated) {
    // We only want to listen to events which are when a Page is created.
    // This filters out all other target types are created, e.g service
    // workers, shared workers, and background pages.
    fmt.Println(e.TargetInfo.Type)
    fmt.Println(proto.TargetTargetInfoTypePage)
    if e.TargetInfo.Type != proto.TargetTargetInfoTypePage {
    return
    }

    // We use the ID to obtain the page ourselves to use.
    page02 := browser.PageFromTargetID(e.TargetInfo.TargetID)
    fmt.Println(page02)
    // Log "hey" on each newly created page.
    page02.Eval(`Object.defineProperty(navigator, 'webdriver', {
    get: () => undefined
    })`)
    })()

    按照官网例子还是不行呢
    ysmood
        57
    ysmood  
    OP
       2020-07-24 18:25:01 +08:00 via Android
    @abc0707 朋友我们没有这样的例子,我们的例子是这个啊 https://github.com/go-rod/bypass/blob/master/example/main.go
    abc0707
        58
    abc0707  
       2020-07-24 21:43:30 +08:00
    好的 这个是看 issue 里面的 我去试试你说的这个
    abc0707
        59
    abc0707  
       2020-07-24 21:46:37 +08:00
    大佬 有没有交流群啊 之前的一个项目加了反爬虫 好多验证 今天刚搜索到这个库感觉还可以
    abc0707
        60
    abc0707  
       2020-07-24 21:51:26 +08:00
    bypass.Page 如何设置 .Headless(false) 这个呢
    abc0707
        61
    abc0707  
       2020-07-24 22:11:58 +08:00
    代码

    package main

    import (
    "fmt"

    "github.com/go-rod/bypass"
    "github.com/go-rod/rod"
    "github.com/go-rod/rod/lib/launcher"
    )

    func main() {
    url := launcher.New().Headless(false).Client()

    browser := rod.New().Client(url).Connect()
    defer browser.Close()

    page := bypass.Page(browser)

    page.Navigate("https://www.baidu.com").WaitLoad()

    page.ScreenshotFullPage("testresult.png")

    fmt.Println("All done, check the screenshot. ✨")
    }

    报错:
    panic: malformed ws or wss URL

    goroutine 1 [running]:
    github.com/ysmood/kit/pkg/utils.E(0xc000042ca0, 0x1, 0x1, 0xe53e98, 0x0, 0x0)
    D:/Program Files/Gopath/src/github.com/ysmood/kit/pkg/utils/utils.go:33 +0xb2
    github.com/go-rod/rod.(*Browser).Connect(0xc00007c880, 0xc0003a26c0)
    D:/Program Files/Gopath/src/github.com/go-rod/rod/sugar.go:18 +0xa4
    main.main()
    c:/Users/zhaob/Desktop/qingdao/main.go:14 +0x94
    exit status 2
    ysmood
        62
    ysmood  
    OP
       2020-07-24 22:41:23 +08:00
    @abc0707 你用法的问题应该用 url := launcher.New().Headless(false).Launch() ,麻烦看看文档再用。Client 这个函数是有说明的。

    交流群已经在这个帖子里提及了啊,你没看到吗?本页面内搜索 聊天室
    ysmood
        63
    ysmood  
    OP
       2020-07-24 22:42:52 +08:00
    @abc0707 不要再直接贴代码了,有问题去群里问,也可以去开 issue,v2ex 贴代码太难以阅读了
    abc0707
        64
    abc0707  
       2020-07-24 22:43:06 +08:00
    好的 谢谢
    fengjianxinghun
        65
    fengjianxinghun  
       2020-07-30 13:15:41 +08:00
    这东西不错,回头试试。
    shuirong1997
        66
    shuirong1997  
       2023-05-26 15:39:58 +08:00
    お問い合わせ内容お問い合わせ内容お問い合わせ内容お問い合わせ内容お問い合わせ内容お問い合わせ内容
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   2732 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 45ms · UTC 12:25 · PVG 20:25 · LAX 05:25 · JFK 08:25
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.