返回

AppleScript Chrome页面加载检测:3种方案详解

javascript

Applescript:Chrome页面加载完成检测

网页自动化任务中,经常需要在页面完全加载后才能进行后续操作。使用 Applescript 操作浏览器时,一个常见的问题是如何准确判断页面是否已经完全加载完成。本篇文章聚焦在使用 Chrome 时如何实现这一目标,并提供多种可行方案。

问题根源

在 Safari 中,通过 document.readyState 属性可以较好地判断页面加载状态。但 Chrome 的行为略有不同,直接沿用 Safari 的检测方法可能会导致脚本执行不稳定或失效。 究其原因,Chrome 中页面的 document.readyState 状态可能在某些复杂场景下并不代表页面元素已经全部渲染完成。 简而言之,简单依靠 document.readyStatecomplete 状态不能完全保证所有资源都加载完毕。

解决方案

针对这一问题,存在多种方法检测 Chrome 页面的加载状态。 每种方法都略有不同,适合不同的应用场景。

方案一:基于 document.readyStatesetTimeout 的循环检测

此方案通过结合 document.readyStatesetTimeout 实现。 它在一定时间间隔内检查 readyState,如果未能及时完成则继续检查。这引入了额外的等待时间,可以提高检测的可靠性。

tell application "Google Chrome"
	set targetTab to active tab of front window
	repeat
		try
			set jsReadyState to execute javascript "document.readyState" in targetTab
			if jsReadyState is "complete" then
				exit repeat
			end if
			delay 0.2
		on error
			-- 页面可能还没初始化完毕
			delay 0.1
		end try
	end repeat
end tell

操作步骤:

  1. 复制以上代码到 “脚本编辑器”。
  2. 确保 Chrome 浏览器处于活动窗口,且要操作的页面已打开。
  3. 运行脚本,它将等待页面加载完成后结束。

工作原理: 脚本通过循环检测页面的 document.readyState 属性。每隔0.2秒进行一次检查,如果为 "complete" ,循环结束。 如果页面尚未加载完成, 则进入下一次检查循环,通过增加一定时间的等待确保资源加载到位,try on error 防止 javascript 初始化未完成报错。

方案二:轮询 DOM 元素是否存在

如果希望在特定元素渲染完成后再进行操作,可以轮询特定 DOM 元素是否存在。 比如判断一个特定按钮或者一个标志性容器元素是否被加载完成。 这个方法更为精准,特别是在一些页面使用懒加载的情况下。

tell application "Google Chrome"
	set targetTab to active tab of front window
	repeat
		try
			set jsResult to execute javascript "document.querySelector('#element-id')" in targetTab
			if jsResult is not missing value then
				exit repeat
			end if
		on error
			-- 元素可能尚未初始化完成
			delay 0.1
		end try
		delay 0.2
	end repeat
end tell

操作步骤:

  1. 将上述代码中的 #element-id 替换为需要检测的 DOM 元素 ID。
  2. 复制修改后的代码到 “脚本编辑器”。
  3. 在Chrome中打开要操作的页面,并且确保要等待的元素在该页面存在。
  4. 运行脚本。 脚本会等待指定 DOM 元素加载完成,随后结束运行。

工作原理: 该脚本定期检测指定 ID 的 DOM 元素是否存在。通过 Javascript的document.querySelector 选择器查询是否存在对应的ID的 DOM 节点,当元素被加载进DOM 后, 返回对应 node 信息;如果不存在会返回 missing valuedelaytry ... on error 的运用,目的是增加脚本稳定性和鲁棒性。

方案三:页面加载事件监控

这种方式直接监听 Chrome 的加载事件,并在加载完成后执行操作。 使用 addEventHandler 在Chrome的 onreadystatechange 中注册回调函数, 来达到异步监听效果,但直接使用Applescript 完成比较复杂。建议配合 Javascript 使用。

    let loadingPromise = new Promise((resolve) => {
    if(document.readyState == 'complete') {
      resolve()
      return;
    }
      document.addEventListener('readystatechange', () => {
         if(document.readyState == 'complete') {
            resolve()
         }
       });
    });

以上Javascript 函数可以包装成脚本在Applescript里执行:

tell application "Google Chrome"
	set targetTab to active tab of front window
   	set javascriptCode to "
	 let loadingPromise = new Promise((resolve) => {
	    if(document.readyState == 'complete') {
	       resolve()
	       return;
	    }
       document.addEventListener('readystatechange', () => {
           if(document.readyState == 'complete') {
              resolve()
           }
        });
     });
  	loadingPromise.then( () => { window.applescriptReturn = 'ready'})
    "

   	execute javascript javascriptCode in targetTab

   	repeat until execute javascript "window.applescriptReturn" in targetTab is "ready"
	  	delay 0.1
   end repeat
	-- 后续操作
end tell

操作步骤:

  1. 复制上述代码至“脚本编辑器”。
  2. 在 Chrome 中打开需要操作的页面。
  3. 运行脚本。 脚本在页面加载完成后,会进行下一步操作。

工作原理: 该方法结合Javascript promise 来监控onreadystatechange 的状态变化,通过 Javascript 给全局增加一个 window.applescriptReturn 返回,通过这个返回的状态是否改变来确定是否页面已经准备好。 这个方法比方案一、方案二更为可靠,通过 onreadystatechange 更贴近于系统层,减少无效的检测,节省性能。

总结

本篇文章提供了多种解决在 Applescript 中等待 Chrome 页面加载完成的方案, 并对每个方案的操作方式以及实现原理进行了解释说明。实际运用中,开发者应根据具体场景需求选择最适合的方法。 可以结合不同方案的特点,选择最合适的。 适当结合使用 try ... on error 可以有效提高脚本运行的健壮性。