51Testing软件测试论坛

 找回密码
 (注-册)加入51Testing

QQ登录

只需一步,快速开始

微信登录,快人一步

手机号码,快捷登录

查看: 1280|回复: 0
打印 上一主题 下一主题

[原创] Web测试好帮手Rod(二)

[复制链接]
  • TA的每日心情
    无聊
    昨天 09:05
  • 签到天数: 1050 天

    连续签到: 1 天

    [LV.10]测试总司令

    跳转到指定楼层
    1#
    发表于 2022-11-2 13:15:41 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
    进入浏览器
      截屏,输出 PDF,或者打印都是很有效的工具。但毕竟只包含结果。有些时候,我们希望直接进入这个浏览器,看看到底发生了什么,rod 当然也是支持的。为了方便调试,我们可以把一些高阶的调试 option 打开,修改上面代码如下:
    1. <font size="3">package main




    2. import (

    3.     "time"




    4.     "github.com/go-rod/rod"

    5. )




    6. func main() {

    7.     page := rod.New().NoDefaultDevice().MustConnect().MustPage("https://www.wikipedia.org/")

    8.     page.MustWindowFullscreen()

    9.     page.MustWaitLoad().MustScreenshot("a.png")

    10.     time.Sleep(time.Hour)

    11. }</font>
    复制代码
    NoDefaultDevice 和 MustWindowFullscreen 能够将页面最大化,方便我们观看;
      这里我们也加上 time.Sleep 让它保持一段时间。
      运行命令:



    1. <font size="3">go run . -rod=show</font>
    复制代码
    这里的选项 show 意味着在前台展示浏览器的 UI,我们就会看到这样的页面:





    我们可以使用 ctrl+c 来停止调试。
      输入和点击
      仅仅能够打开网页显然不足以满足我们的诉求,下面我们来看看怎样去操纵页面上的元素。还是以刚才的 wikipedia 页面为例,我们来看一个示例,如何通过代码,让网页自动去搜索,返回搜索结果。
      还是原来的代码,我们稍微修改一下启动命令:



    1. <font size="3">go run . -rod=show,devtools</font>
    复制代码


    和此前一样,程序会自动打开一个浏览器页面,进入 wikipedia。这时我们需要通过一些手动 inspect 操作,找到输入框的 selector:








    找到输入框 selector 后,copy 出来,这里我们会得到 #searchInput。
      修改一下代码:



    1. <font size="3">package main




    2. import (

    3.     "time"




    4.     "github.com/go-rod/rod"

    5. )




    6. func main() {

    7.     browser := rod.New().MustConnect().NoDefaultDevice()

    8.     page := browser.MustPage("https://www.wikipedia.org/").MustWindowFullscreen()




    9.     page.MustElement("#searchInput").MustInput("earth")




    10.     page.MustWaitLoad().MustScreenshot("a.png")

    11.     time.Sleep(time.Hour)

    12. }</font>
    复制代码


    注意,我们的修改仅仅是加上了 page.MustElement("#searchInput").MustInput("earth")。
      MustElement 会帮助我们根据选择器,获取到对应的元素,返回了一个 Element。这里自动处理了等待加载的过程,所以我们不需要再次调用 MustWaitLoad 来阻塞。



    1. <font size="3">// MustElement is similar to Page.Element

    2. func (p *Page) MustElement(selector string) *Element {

    3. el, err := p.Element(selector)

    4. p.e(err)

    5. return el

    6. }




    7. // Element retries until an element in the page that matches the CSS selector, then returns

    8. // the matched element.

    9. func (p *Page) Element(selector string) (*Element, error) {

    10. return p.ElementByJS(evalHelper(js.Element, selector))

    11. }</font>
    复制代码


    MustInput 是 Element 的方法,输入我们指定的文本。注意,Input 前会保证当前 Element 是可见的,可写入的,和我们自己打开浏览器页面等待加载的过程是一样的。使用空字符串则可以请求空 Element 的文本。


    1. <font size="3">// MustInput is similar to Element.Input

    2. func (el *Element) MustInput(text string) *Element {

    3. el.e(el.Input(text))

    4. return el

    5. }




    6. // Input focuses on the element and input text to it.

    7. // Before the action, it will scroll to the element, wait until it's visible, enabled and writable.

    8. // To empty the input you can use something like el.SelectAllText().MustInput("")

    9. func (el *Element) Input(text string) error </font>
    复制代码


    好了,现在我们重新执行 main.go,输入框会按照我们预期,输入了 earth 这个字符串:





    第一步完成,下一步,我们需要点击那个【搜索按钮】,让浏览器自动跳转到搜索结果页。
      这里的操作也是类似的,我们就不再赘述。需要大家自行通过 chrome 的 inspect 找到搜索button的 selector,然后修改代码,配合点击即可。
      修改后的代码如下:



    1. <font size="3">package main




    2. import (

    3.     "time"




    4.     "github.com/go-rod/rod"

    5. )




    6. func main() {

    7.     browser := rod.New().MustConnect().NoDefaultDevice()

    8.     page := browser.MustPage("https://www.wikipedia.org/").MustWindowFullscreen()




    9.     page.MustElement("#searchInput").MustInput("earth")

    10.     page.MustElement("#search-form > fieldset > button").MustClick()




    11.     page.MustWaitLoad().MustScreenshot("a.png")

    12.     time.Sleep(time.Hour)

    13. }</font>
    复制代码


    注意,这里我们多了个新的方法,也是 Element 下面的:


    1. <font size="3">// MustClick is similar to Element.Click

    2. func (el *Element) MustClick() *Element {

    3. el.e(el.Click(proto.InputMouseButtonLeft, 1))

    4. return el

    5. }




    6. // Click will press then release the button just like a human.

    7. // Before the action, it will try to scroll to the element, hover the mouse over it,

    8. // wait until the it's interactable and enabled.

    9. func (el *Element) Click(button proto.InputMouseButton, clickCount int) error {

    10. err := el.Hover()

    11. if err != nil {

    12. return err

    13. }




    14. err = el.WaitEnabled()

    15. if err != nil {

    16. return err

    17. }




    18. defer el.tryTrace(TraceTypeInput, string(button)+" click")()




    19. return el.page.Mouse.Click(button, clickCount)

    20. }</font>
    复制代码


    MustClick 会模拟我们人工的操作,尝试滚到我们的 Element 位置,把鼠标挪上去,等待可点击。随后触发点击事件。
      这样一来,我们重新运行 main.go,输出的 a.png 就会给我们 earth 的搜索结果了:






    Slow Motion
      rod 还提供了 slow motion 和 trace 的功能,方便我们在浏览器上观察发生的动作,让执行慢下来,这样我们才好观察到。
      修改启动命令如下:



    1. <font size="3">go run . -rod="show,slow=1s,trace"</font>
    复制代码


    这样就启动了 slow motion,所有动作执行前都会等待 1 秒钟。





    我们还可以从 console(控制台)看到发生的动作:


    1. <font size="3">[rod] 2020/11/11 11:11:11 [eval] {"js":"rod.element","params":["#searchInput"]}

    2. [rod] 2020/11/11 11:11:11 [eval] {"js":"rod.visible","this":"input#searchInput"}

    3. [rod] 2020/11/11 11:11:11 [input] scroll into view

    4. [rod] 2020/11/11 11:11:11 [input] input earth

    5. [rod] 2020/11/11 11:11:11 [eval] {"js":"rod.element","params":["#search-form > fieldset > button"]}

    6. [rod] 2020/11/11 11:11:11 [eval] {"js":"rod.visible","this":"button.pure-button.pure-button-primary-progressive"}

    7. [rod] 2020/11/11 11:11:11 [input] scroll into view

    8. [rod] 2020/11/11 11:11:11 [input] left click</font>
    复制代码


     除了命令行里通过参数指定,我们还可以直接通过代码实现,slow motion 通过链式API 就可以做到:rod.New().SlowMotion(2 * time.Second)
      获取文本
      到这里其实就是经典的爬虫做法了,同样我们需要通过 inspect 拿到 selector:






    前面我们见识了MustInput 以及MustClick,获取文本这里则需要用到 MustText。


    1. <font size="3">// MustText is similar to Element.Text

    2. func (el *Element) MustText() string {

    3. s, err := el.Text()

    4. el.e(err)

    5. return s

    6. }




    7. // Text that the element displays

    8. func (el *Element) Text() (string, error) {

    9. str, err := el.Evaluate(evalHelper(js.Text))

    10. if err != nil {

    11. return "", err

    12. }

    13. return str.Value.String(), nil

    14. }</font>
    复制代码


    底层获取到 Element 中的文本,以 string 返回回来,非常简单。我们修改下代码:


    1. <font size="3">package main




    2. import (

    3.     "fmt"




    4.     "github.com/go-rod/rod"

    5. )




    6. func main() {

    7.     page := rod.New().MustConnect().MustPage("https://www.wikipedia.org/")




    8.     page.MustElement("#searchInput").MustInput("earth")

    9.     page.MustElement("#search-form > fieldset > button").MustClick()




    10.     el := page.MustElement("#mw-content-text > div.mw-parser-output > p:nth-child(6)")

    11.     fmt.Println(el.MustText())

    12. }</font>
    复制代码


    重新运行项目,这是我们不再看到截屏,而是在命令行看到爬下来的文本:


    1. <font size="3">Earth is the third planet from the Sun and the only astronomical object known to harbor life.

    2. ...</font>
    复制代码



    本帖子中包含更多资源

    您需要 登录 才可以下载或查看,没有帐号?(注-册)加入51Testing

    x
    分享到:  QQ好友和群QQ好友和群 QQ空间QQ空间 腾讯微博腾讯微博 腾讯朋友腾讯朋友
    收藏收藏
    回复

    使用道具 举报

    本版积分规则

    关闭

    站长推荐上一条 /1 下一条

    小黑屋|手机版|Archiver|51Testing软件测试网 ( 沪ICP备05003035号 关于我们

    GMT+8, 2024-11-22 02:38 , Processed in 0.067207 second(s), 23 queries .

    Powered by Discuz! X3.2

    © 2001-2024 Comsenz Inc.

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