pin_drop当前位置:知识文库 ❯ 图文

Selenium执行JavaScript教程 - execute_script与异步方法详解

Selenium执行JavaScript教程 - execute_script完整指南

一、执行JavaScript概述

Selenium通过execute_script()execute_async_script()方法在浏览器中直接执行JavaScript代码。这为自动化测试提供了强大的扩展能力,可以完成Selenium原生API不支持的操作,如滚动页面修改元素样式获取页面性能数据触发自定义事件等。

当Selenium原生方法无法满足需求时,执行JavaScript是最强大的补充手段,几乎可以操作页面上的任何内容。


二、同步执行execute_script

execute_script()是同步执行方法,会阻塞等待JavaScript代码执行完成并返回结果。这是最常用的JS执行方式。

语法格式

代码示例

# 同步执行
result = driver.execute_script(script, *args)

参数说明

参数 类型 必填 说明
script str JavaScript代码字符串
*args any 传递给JS的参数,在JS中通过arguments访问

三、异步执行execute_async_script

execute_async_script()用于执行异步JavaScript代码,适用于需要等待回调的场景,如setTimeout、Promise、Ajax请求等。

语法格式

代码示例

# 异步执行
result = driver.execute_async_script(script, *args)

重要提示:异步脚本中必须调用arguments[arguments.length - 1]作为回调函数来表示执行完成,否则会超时抛出异常。

代码示例

# 异步执行示例:等待3秒后返回结果
result = driver.execute_async_script("""
    var callback = arguments[arguments.length - 1];
    setTimeout(function() {
        callback('异步任务完成');
    }, 3000);
""")
print(result)  # 输出: 异步任务完成

四、Python与JavaScript数据传递

Selenium自动处理Python与JavaScript之间的数据类型转换,支持双向数据传递:

Python类型 JS中对应类型 说明
int / float Number 数值类型
str String 字符串
bool Boolean 布尔值
list Array 数组
dict Object 对象
WebElement HTMLElement DOM元素

五、代码示例详解

示例1:页面滚动操作

使用JavaScript控制页面滚动是最常见的应用场景之一,包括滚动到顶部、底部、指定位置或滚动到特定元素:

代码示例

from selenium import webdriver
from selenium.webdriver.common.by import By

driver = webdriver.Chrome()
driver.get("https://www.example.com")
driver.set_window_size(800, 600)

# 滚动到页面底部
driver.execute_script("window.scrollTo(0, document.body.scrollHeight);")
print("已滚动到页面底部")

# 滚动到页面顶部
driver.execute_script("window.scrollTo(0, 0);")
print("已滚动到页面顶部")

# 滚动到指定位置
driver.execute_script("window.scrollTo(0, 300);")
print("已滚动到300px位置")

# 滚动到元素位置
element = driver.find_element(By.TAG_NAME, 'h1')
driver.execute_script("arguments[0].scrollIntoView();", element)
print("已滚动到元素位置")

driver.quit()

输出结果:

代码示例

已滚动到页面底部
已滚动到页面顶部
已滚动到300px位置
已滚动到元素位置

示例2:修改元素样式和属性

通过JavaScript可以直接修改DOM元素的样式、文本内容、属性等,这在处理隐藏元素或改变页面状态时非常有用:

代码示例

from selenium import webdriver
from selenium.webdriver.common.by import By

driver = webdriver.Chrome()
driver.get("https://www.example.com")

heading = driver.find_element(By.TAG_NAME, 'h1')

# 修改元素样式
driver.execute_script(
    "arguments[0].style.color = 'red'; arguments[0].style.fontSize = '50px';",
    heading
)
print("已修改标题样式为红色50px")

# 修改元素文本
driver.execute_script("arguments[0].textContent = 'Modified by JS';", heading)
print(f"修改后文本: {heading.text}")

# 获取元素属性
text = driver.execute_script("return arguments[0].textContent;", heading)
print(f"JS获取文本: {text}")

# 隐藏元素
driver.execute_script("arguments[0].style.display = 'none';", heading)
print("已隐藏标题元素")

driver.quit()

输出结果:

代码示例

已修改标题样式为红色50px
修改后文本: Modified by JS
JS获取文本: Modified by JS
已隐藏标题元素

示例3:获取页面性能数据

通过JavaScript可以获取浏览器内置的性能API数据、页面尺寸、DOM元素信息等:

代码示例

from selenium import webdriver

driver = webdriver.Chrome()
driver.get("https://www.example.com")

# 获取页面性能数据
performance = driver.execute_script(
    "return JSON.stringify(window.performance.timing);"
)
print(f"性能数据: {performance[:100]}...")

# 获取页面高度
page_height = driver.execute_script("return document.body.scrollHeight;")
print(f"页面高度: {page_height}px")

# 获取视口尺寸
viewport = driver.execute_script(
    "return {width: window.innerWidth, height: window.innerHeight};"
)
print(f"视口尺寸: {viewport}")

# 获取所有链接
links = driver.execute_script(
    "return Array.from(document.querySelectorAll('a')).map(a => a.href);"
)
print(f"链接数量: {len(links)}")
for link in links:
    print(f"  {link}")

driver.quit()

输出结果:

代码示例

性能数据: {"navigationStart":1704067200000,"unloadEventStart":0,...
页面高度: 800px
视口尺寸: {'width': 800, 'height': 600}
链接数量: 1
  https://www.iana.org/domains/example

六、实际应用场景

  • 无限滚动页面处理:对于采用懒加载的无限滚动页面(如微博、小红书),可以通过JS逐步滚动到底部,触发内容加载,直到获取全部数据。

  • 隐藏元素操作:某些表单或按钮可能被CSS隐藏(display:none),通过JS修改样式使其可见,然后进行Selenium操作。

  • 页面性能监控:获取window.performance.timing数据,监控页面加载速度、DOM渲染时间等性能指标,用于性能测试和回归检测。

小贴士

在处理复杂JS代码时,建议使用三引号"""..."""包裹多行JavaScript代码,提高可读性。同时可以使用return语句将JS计算结果返回给Python。


七、执行方式对比

执行方式 方法 特点 适用场景
同步执行 execute_script() 阻塞等待结果,代码执行完立即返回 大多数场景:滚动、修改样式、获取数据
异步执行 execute_async_script() 非阻塞,需调用callback表示完成 需等待异步操作:setTimeout、Ajax、Promise

八、注意事项

⚠️ 注意1:execute_script()中的JS代码在浏览器沙箱中执行,受同源策略限制,无法跨域访问其他页面的数据。

⚠️ 注意2:传递WebElement给JS时使用arguments[0]、arguments[1]等索引引用,不是直接使用变量名。

⚠️ 注意3:execute_async_script()必须在JS代码中调用callback函数(即arguments[arguments.length - 1])表示完成,否则会因超时而抛出TimeoutException。

⚠️ 注意4:JS执行出错时Selenium会抛出JavascriptException,可以使用try-except捕获异常进行处理。


九、练习题

练习1

编写程序,使用execute_script()实现页面平滑滚动效果,从顶部平滑滚动到底部。

练习2

编写程序,使用execute_script()获取页面中所有图片的URL和尺寸信息,并打印输出。


常见问题

execute_script和execute_async_script有什么区别?

execute_script是同步执行,等待JS代码执行完成后立即返回结果,适用于大多数场景。execute_async_script是异步执行,需要在JS中手动调用callback表示完成,适用于需要等待异步操作的场景,如setTimeout、Ajax请求等。

如何在JS代码中引用Python的WebElement?

将WebElement作为execute_script的第二个参数传入,在JS中通过arguments[0]访问。例如:driver.execute_script("arguments[0].click();", element)。多个元素依次使用arguments[1]、arguments[2]等。

execute_async_script的callback函数在哪里?

callback函数自动作为arguments数组的最后一个元素传入。可以通过arguments[arguments.length - 1]获取,通常建议在JS开头定义:var callback = arguments[arguments.length - 1];,然后在异步操作完成后调用callback(result)返回结果。

如何使用JS实现页面平滑滚动?

可以使用window.scrollTo()的behavior选项实现平滑滚动:driver.execute_script("window.scrollTo({top: document.body.scrollHeight, behavior: 'smooth'});")。这需要浏览器支持CSSOM View规范,现代浏览器均支持。

JS执行报错JavascriptException如何调试?

可以先在浏览器开发者工具的Console中直接运行相同的JS代码进行测试,确认语法无误后再放入execute_script中。也可以使用try-except捕获JavascriptException,打印异常信息定位问题。

标签: Selenium execute_script JavaScript 页面滚动 自动化测试 性能监控 异步执行

本文涉及AI创作

内容由AI创作,请仔细甄别

list快速访问

上一篇: Selenium截图教程 - save_screenshot页面元素截图方法 下一篇: Selenium ActionChains教程 - 鼠标悬停拖拽组合键操作

poll相关推荐