sas 发表于 2022-7-2 12:43

[aardio] 使用开发工具协议控制谷歌浏览器

本帖最后由 sas 于 2022-7-2 21:55 编辑

本帖子的代码基于此扩展库 https://github.com/btx638/aaz-aardio,下载后把 aaz 目录放到 aardio 的 lib 目录,就可以运行帖子的代码
国内备份仓库 https://gitcode.net/vmax666/aaz-aardio

chrome 开发工具协议:https://chromedevtools.github.io/devtools-protocol/

范例1: 打开 360搜索 ,搜索 52pojie



import win.ui;
/*DSG{{*/
var winform = win.form(text="aardio form";right=385;bottom=140)
winform.add(
button={cls="button";text="运行";left=142;top=43;right=221;bottom=83;z=1}
)
/*}}*/

io.open()

import aaz.chrome.dp;

var cdp, err = aaz.chrome.dp()
if(!cdp){
    winform.msgboxErr(err);
    return ;
}

// 指定每个步骤的超时, 这里是2万毫秒,就是20秒
cdp.timeout = 20000;

// 定义任务函数
var task = function(){
    // 打开浏览器
    var ok, err = cdp.open()
    if(!ok){
         io.print("打开浏览器失败", err);
      return ;
    }
   
    // 连接浏览器
    var ok, err = cdp.connect();
    if(!ok){
      io.print("连接浏览器失败", err);
      return ;
    }

    // 订阅 Page 事件   
    var ok, err = cdp.Page.enable();
    if(!ok){
      io.print("订阅 Page 事件失败", err);
      return ;
    }

    // 打开网址
    var ok, err = cdp.Page.navigate(
      url = "https://www.so.com";
    )
    if(!ok){
      io.print("打开网址失败", err)
      return ;
    }
   
    // 等待页面加载完成
    var ok, err = cdp.waitEvent( "Page.loadEventFired" );
    if(!ok){
      io.print("等待页面加载完成失败", err);
      return ;
    }


    // 执行 js 脚本
    var ok, err = cdp.Runtime.evaluate(
      expression = /**
       document.querySelector("#input").value = "52pojie";
       document.querySelector("#search-button").click();
      **/
    )

}

// 点击运行任务函数
winform.button.oncommand = function(id,event){
    cdp.run(task)
}

winform.show();
win.loopMessage();

范例2:定义一个等待函数, 可以在任务函数里面使用

// 定义 js 等待函数
var waitJs = /**
    const userWait = (ms) => {
      return new Promise(resolve => setTimeout(resolve, ms))
    }
   
    async function sleepAsync(ms) {
      await userWait(ms)
    }
**/

// 向网页载入 js 代码
var loadCode = function(js){
    return cdp.Runtime.evaluate(
      expression = js;
    )   
}

// 等待函数
var wait = function(ms){
    return cdp.Runtime.evaluate(
      awaitPromise = true; // 执行是否应该等待结果值,并在等待的承诺被解决后返回。
      expression = string.format("sleepAsync(%s)", ms)
    )
}


范例3:使用等待函数,用于截图任意网站的完整的首页, 先试试截图淘宝



import win.ui;
/*DSG{{*/
var winform = win.form(text="aardio form";right=623;bottom=103)
winform.add(
btnScreenshot={cls="button";text="截图";left=440;top=16;right=576;bottom=48;z=3};
edUrl={cls="edit";text="https://www.taobao.com/";left=72;top=16;right=424;bottom=48;edge=1;z=2};
static={cls="static";text="网址:";left=24;top=16;right=72;bottom=48;transparent=1;z=1};
static2={cls="static";text="日志:";left=80;top=72;right=288;bottom=88;transparent=1;z=4}
)
/*}}*/

// https://dschnurr.medium.com/usin ... t-tool-4b07dffba79a
// https://blog.csdn.net/z69183787/article/details/91984005
// https://dev.to/gdledsan/selenium ... age-screenthos-2j8d
// https://github.com/puppeteer/pup ... ommon/Page.ts#L2741


import crypt.bin
import process
import aaz.chrome.dp;

var cdp, err = aaz.chrome.dp()
// 定义 js 等待函数
var waitJs = /**
    const userWait = (ms) => {
      return new Promise(resolve => setTimeout(resolve, ms))
    }
   
    async function sleepAsync(ms) {
      await userWait(ms)
    }
**/

// 向网页载入 js 代码
var loadJsCode = function(js){
    return cdp.Runtime.evaluate(
      expression = js;
    )   
}

// 等待函数
var wait = function(ms){
    return cdp.Runtime.evaluate(
      awaitPromise = true; // 执行是否应该等待结果值,并在等待的承诺被解决后返回。
      expression = string.format("sleepAsync(%s)", ms)
    )
}

io.open()
var task = function(url){
    // 以无头模式启动,就是不显示浏览器的界面
    cdp.open(,true)
    cdp.connect();
    // 订阅 Page 事件,可用于等待页面加载完成
    cdp.Page.enable();
    // 打开网址
    cdp.Page.navigate(
      url = url;
    )
    // 等待页面加载完成
    cdp.waitEvent( "Page.loadEventFired" );
   
    // 载入等待js函数
    loadJsCode(waitJs)
   
    // 已滚动的总高度
    var scrolledDistance = 0;
    // 每次滚动高度
    var distance = 100;
   
    while(true){
      // 滚动一次
      cdp.Runtime.evaluate(
            expression = string.format(" window.scrollBy(0, %s);", distance);
      )
      // 记录已滚动的高度
      scrolledDistance += distance;
      
      // 滚动条的实际高度
      var ret = cdp.Runtime.evaluate(
            expression = "document.body.scrollHeight";
            returnByValue = true;
      )
      
      // 定义一个回调函数,用于输出日志
      if(onSroll){
            onSroll(scrolledDistance, ret.result.value)
      }
      
      // 滚动到底了
      if (scrolledDistance >= ret.result.value) {
          break;
      }

      // 等待100毫秒,让网页加载新的内容,如果网络慢可以加大等待时间
      wait(100)
      
    }
   

    var rect = cdp.Page.getLayoutMetrics()
   
    // 截图
    var ret = cdp.Page.captureScreenshot(
      format="jpeg";
      captureBeyondViewport = true;

      clip = {
            x = 0;
            y = 0;
            scale = 1;
            width = rect.cssContentSize.width;
            height = rect.cssContentSize.height;
      }

    )
   
    // 关闭浏览器
    cdp.Browser.close();
    if(ret){
      // 输出解码后的图像数据
      return crypt.bin.decodeBase64(ret.data);   
    }
}

onSroll = function(scrolledDistance, mian){
    winform.static2.text = "已滚动距离:" ++ scrolledDistance ++ " 总高度:" ++ mian
}


winform.btnScreenshot.oncommand = function(id,event){
    var url = winform.edUrl.text
    if(!string.startWith(url, "http")){
      winform.msgboxErr("请填写网址")
      return ;
    }
   
    // 执行任务函数
    cdp.run(
      task,
      // 执行前触发
      function(){
            winform.btnScreenshot.disabled = true
      },
      // 执行完毕触发,并收到执行函数的返回值
      function(data){
            winform.btnScreenshot.disabled = false
            if(data){
                string.save("\截图.jpg", data)
                process.exploreSelect("\截图.jpg")
            }
      },
      url
    )
}


winform.show();
win.loopMessage();
return winform;

wh201906 发表于 2022-7-2 20:43

本帖最后由 wh201906 于 2022-12-16 22:40 编辑

sas 发表于 2022-7-2 16:32
selenium 应该是用开发工具协议封装的, 这个是直接用开发工具协议,没有什么封装
https://chromedevtoo ...
selenium支持的浏览器会更多一些,比如Chrome, IE, Safari, Opera, Firefox这些,所以想了解一下这个aardio是不是有什么其它的亮点

sas 发表于 2022-7-2 16:32

本帖最后由 sas 于 2022-7-2 16:40 编辑

XiaoZouYu 发表于 2022-7-2 16:22
我也是想问问这个问题
selenium 应该是用开发工具协议封装的, 这个是直接用开发工具协议,没有什么封装
https://chromedevtools.github.io/devtools-protocol/

success666 发表于 2022-7-2 13:18

正好要学习这个技术,就看到楼主的贴子了

CXC303 发表于 2022-7-2 13:29

标记学习

wh201906 发表于 2022-7-2 13:57

这个和selenium相比如何呢?

XiaoZouYu 发表于 2022-7-2 16:22

wh201906 发表于 2022-7-2 13:57
这个和selenium相比如何呢?

我也是想问问这个问题:Dweeqw

xinyangtuina 发表于 2022-7-2 20:37

学习了。理解为是用aardio来做网页自动化。

benny856694 发表于 2022-7-2 21:39

高级的东西

xiadongming 发表于 2022-7-2 22:44

页: [1] 2
查看完整版本: [aardio] 使用开发工具协议控制谷歌浏览器