找回密码
 立即注册
首页 业界区 科技 selenium之javascript语句的执行

selenium之javascript语句的执行

戎玉珂 2025-6-8 22:08:06
今天来学习以下selenium怎么执行Js脚本的
在平时使用selenium的时候,有些操作我们需要借助js代码,才可以更加方便快捷;下面就让我们看一看怎么执行js代码
当然了,首先就是写一段js代码;这里就需要你有js相关的知识了;当然,没有也可以;现在AI这么方便,你可以让AI帮你写一段你想要用的js代码
selenium执行js代码,主要有两种方式

  • 同步执行execute_script()
  • 异步执行execute_async_script()
那么这两种方式有什么不一样的吗,它们的关键区别就是如何处理脚本的执行和完成;
同步执行execute_script()


  • 执行方式:这意味着 Selenium 会等待你提供的 JavaScript 代码完全执行完毕并返回结果(如果有)后,才会继续执行 Python 脚本中的下一行代码。
  • 使用场景:适用于执行不需要等待异步操作完成的 JavaScript 代码

    • 获取页面属性(如 document.title, element.textContent)
    • 简单地修改DOM元素属性
    • 触发元素的同步方法(如 element.click())
    • 执行简单的计算逻辑

  • 返回值:可以返回JS代码执行的结果;结果会被转为Python相应类型;(字符串、数字、DOM对象转为web Element);如果没有明确return语句,或者返回underfined;则会返回给Python给None
  • 回调:不需要显式通知selenium,js代码已经完成
异步执行execute_async_script()


  • 执行方式:当你的 JavaScript 代码包含需要一段时间才能完成的操作(例如使用 setTimeout、setInterval、Promise、XMLHttpRequest 等),你需要使用这个方法。Selenium 不会无限期地等待异步操作完成。你需要显式地在你的 JavaScript 代码中调用一个由 Selenium 注入的回调函数来通知 Selenium 脚本已经执行完毕。
  • 使用场景:适用于需要等待异步操作完成的 JavaScript 代码

    • 等待AJAX请求完成
    • 设置定时器后执行某些操作
    • 处理动画、过渡效果完成后的状态
    • 与使用Promise的代码进行交互

  • 返回值:execute_async_script() 也可以返回 JavaScript 代码通过回调函数传递的结果。需要将结果作为参数传递给 Selenium 注入的回调函数(通常通过 arguments[arguments.length - 1](result) 的方式调用)。如果在超时时间内没有调用回调函数,Selenium 会抛出一个 TimeoutException
  • 回调:必须在 JavaScript 代码中通过 arguments[arguments.length - 1]() 或 arguments[arguments.length - 1](result) 的方式显式调用回调函数,以通知 Selenium 异步操作已完成并可以继续执行 Python 代码。
那么什么时候使用同步、什么时候使用异步呢?
答案很简单,当你的代码是立即完成的,没有延迟、异步操作;就是同步
当代码需要一段时间才可以完成操作,并且selenium需要这些操作完成后再继续执行,那么就是异步
既然知道了怎么执行js代码;那么就让我们来几个例子实战演示一下把
首先准备工作先做好
  1. class execute_script_js:
  2.     def __init__(self, sevre_path):
  3.         self.sevre_path = sevre_path
  4.         self.service = Service(self.sevre_path)
  5.         self.browser = webdriver.Chrome(service=self.service)
  6.         
  7. if __name__ == '__main__':
  8.     serve_path = r'D:\Code_Study\driver\chromedriver-win64\chromedriver.exe'
  9.     script_js = execute_script_js(serve_path)
复制代码
同步执行execute_script()

获取页面标题
  1.     # 获取title标题
  2.     def execute_script_title(self, js_code):
  3.         self.browser.get(r"https://www.baidu.com/")
  4.         title = self.browser.execute_script(js_code)
  5.         print(f"页面标题是{title}")
  6.         
  7. js_code = "return document.title;"
  8. script_js.execute_script_title(js_code)
复制代码
滚动到页面底部
  1.     # 滚动到页面底部
  2.     def execute_script_scroll(self, js_code):
  3.         self.browser.get(           "https://www.selenium.dev/selenium/web/scrolling_tests/frame_with_nested_scrolling_frame_out_of_view.html")
  4.         time.sleep(5)
  5.         self.browser.execute_script(js_code)
  6.        
  7. js_code = "window.scrollTo(0, document.body.scrollHeight);"
  8. script_js.execute_script_scroll(js_code)
复制代码
点击页面上的一个按钮
  1. # 点击页面上按钮
  2.     def execute_script_button(self, js_code):
  3.         self.browser.get(r"https://www.baidu.com/")
  4.         self.browser.execute_script(js_code)
  5. button_text = "更多"
  6. js_code = f"""
  7.     const elements = document.querySelectorAll("a");
  8.     for (let i = 0; i < elements.length; i++) {{
  9.         if (elements[i].textContent.trim() === '{button_text}'){{
  10.                 elements[i].click();
  11.                 break;
  12.                 }}
  13.             }}
  14.     """
  15. script_js.execute_script_button(js_code)
复制代码
修改页面元素属性
  1.     # # 修改页面元素的属性
  2.     def execute_script_attribute(self, js_code):
  3.         self.browser.get(r"https://www.baidu.com/")
  4.         self.browser.execute_script(js_code)
  5.     # 检查元素属性是否修改
  6.     def check_attribute(self):
  7.         element = self.browser.find_element(By.ID, element_id)
  8.         attribute_value = element.get_attribute(new_attribute)
  9.         print(f"搜索输入框的新属性 '{new_attribute}' 的值是: {attribute_value}")
  10.         
  11.         
  12.         
  13.         
  14. # 获取 id 为 kw 的元素(百度搜索输入框),并将其 placeholder 属性修改为 "Selenium Test Input"。
  15. element_id = "kw"
  16. new_attribute = "placeholder"
  17. new_value = "Selenium Test Input"
  18. js_code = f"""
  19.     const element = document.getElementById('{element_id}');
  20.     if (element){{
  21.         element.setAttribute("{new_attribute}","{new_value}");
  22.     }}
  23.     """
  24. script_js.execute_script_attribute(js_code)
  25. script_js.check_attribute()
复制代码
页面上添加一个用于测试的div元素
  1.    # 再页面上添加一个用于测试的div元素
  2.     def execute_script_add_div(self, js_code_div, js_code):
  3.         self.browser.get(r"https://www.baidu.com/")
  4.         # 同步执行
  5.         self.browser.execute_script(js_code_div)
  6.         # 异步执行
  7.         self.browser.execute_async_script(js_code)
  8.     # 检查div元素是否被添加上
  9.     def check_add_div(self):
  10.         try:
  11.             element = self.browser.find_element(By.ID, element_id)
  12.             print(f"元素的文本内容是: {element.text}")
  13.         except Exception as e:
  14.             print(f"找不到元素或者发生错误:{e}")
  15.             
  16.             
  17.             
  18. # 再页面上添加一个用于测试的div元素
  19. js_code_div = f"""
  20.     const div = document.createElement('div');
  21.     div.id = "asyncDivBaidu";
  22.     div.textContent = "这个是添加的div_Initial Text";
  23.     div.style.border = '1px solid red';
  24.     div.style.padding = '10px';
  25.     document.body.appendChild(div);
  26.   """
  27. element_id = "asyncDivBaidu"
  28. new_text = "Text changed after 2 seconds"
  29. # 使用 setTimeout 延迟后修改页面元素文本
  30. js_code = f"""
  31.     const element = document.getElementById('{element_id}');
  32.     const callback = arguments[arguments.length-1];
  33.     setTimeout(() =>{{
  34.         if (element){{
  35.             element.textContent = '{new_text}';
  36.             }}
  37.             callback();// 必须调用 callback() 来通知 Selenium 脚本完成
  38.     }},2000);
  39. """
  40. script_js.execute_script_add_div(js_code_div, js_code)
  41. time.sleep(5)
  42. script_js.check_add_div()
复制代码
异步执行execute_async_script()

准备工作,声明一个类,初始化的时候;生成webdriver对象
  1. class execute_async_script_js:
  2.     def __init__(self, sevre_path):
  3.         self.sevre_path = sevre_path
  4.         self.service = Service(self.sevre_path)
  5.         self.browser = webdriver.Chrome(service=self.service)
  6.     def close(self):
  7.         time.sleep(5)
  8.         self.browser.quit()
  9.         
  10. if __name__ == '__main__':
  11.     serve_path = r'D:\Code_Study\driver\chromedriver-win64\chromedriver.exe'
  12.     async_script_js = execute_async_script_js(serve_path)
复制代码
延迟修改搜索框的placeholder属性
  1.     # 延迟修改搜索框的placeholder属性
  2.     def execute_async_script_modification(self, js_code):
  3.         self.browser.get("https://www.baidu.com/")
  4.         self.browser.execute_async_script(js_code)
  5.         # 再js延迟期间,python脚本会等待;默认是30s
  6.         print(f"等待 {delay_seconds} 秒后 placeholder 应该会改变...")
  7.         time.sleep(delay_seconds + 1)  # 稍微等待长一点以确保变化发生
  8.     # 检查是否修改
  9.     def check_modification(self):
  10.         element = self.browser.find_element(By.ID, element_id)
  11.         attribute_value = element.get_attribute("placeholder")
  12.         print(f"搜索输入框的palceholder属性为:{attribute_value}")
复制代码
  1. element_id = "kw"
  2. new_placeholder  = "Delayed Input"
  3. delay_seconds = 3
  4. js_code = f"""
  5.         const element = document.getElementById('{element_id}');
  6.         const callback = arguments[arguments.length - 1];
  7.         setTimeout(()=>{{
  8.             if (element){{
  9.                 element.setAttribute('placeholder', '{new_placeholder}');
  10.             }}
  11.             callback();//通知selenium脚本完成
  12.         }},{delay_seconds * 1000});
  13. """
  14. async_script_js.execute_async_script_modification(js_code)
  15. async_script_js.check_modification()
  16. async_script_js.close()
复制代码
延迟后在页面上添加一个新的元素
  1. new_element_id = "delayedElement"
  2. delay_seconds = 2
  3. js_code = f"""
  4. const newDiv = document.createElement('div');
  5. newDiv.id = '{new_element_id}';
  6. newDiv.textContent = 'This element was added after {delay_seconds} seconds.';
  7. const body = document.body;
  8. const callback = arguments[arguments.length - 1];
  9. setTimeout(()=>{{
  10.     body.appendChild(newDiv);
  11.     callback();
  12. }},{delay_seconds * 1000});
  13.    
  14. """
  15. async_script_js.execute_async_script_add_div(js_code)
  16. async_script_js.check_add_div()
复制代码
  1.     # 延迟后在页面上添加一个新的元素
  2.     def execute_async_script_add_div(self, js_code):
  3.         self.browser.get(r"https://www.baidu.com/")
  4.         self.browser.execute_async_script(js_code)
  5.         print(f"等待 {delay_seconds} 秒后应该会看到一个新的 div 元素...")
  6.         time.sleep(delay_seconds + 1)
  7.     # 检查元素是否添加成功
  8.     def check_add_div(self):
  9.         try:
  10.             delayed_element = self.browser.find_element(By.ID, new_element_id)
  11.             print(f"找到新添加的元素,文本内容是: {delayed_element.text}")
  12.         except Exception as e:
  13.             print(f"没有找到新添加的元素: {e}")
复制代码
模拟请求
  1.     # 模拟请求
  2.     delay_seconds = 4
  3.     mock_data = {"Message": "Data loaded successfully after delay"}
  4.     js_code = f"""
  5.     const callback = arguments[arguments.length - 1];
  6.     setTimeout(()=>{{
  7.         const result = JSON.stringify('{json.dumps(mock_data)}');
  8.         callback(result);// 将结果传递给 callback
  9.     }},{delay_seconds * 1000});
  10. """
  11.     res = async_script_js.imitate_req(js_code)
  12.     async_script_js.check_req(result_from_js=res)
复制代码
  1.     # 模拟请求
  2.     def imitate_req(self, js_code):
  3.         self.browser.get(r"https://www.baidu.com/")
  4.         # 执行异步js并取得返回值
  5.         result_from_js = self.browser.execute_async_script(js_code)
  6.         print(f"等待{delay_seconds}s后获取js返回的数据。。。")
  7.         time.sleep(delay_seconds + 1)
  8.         return result_from_js
  9.     def check_req(self,result_from_js):
  10.         if result_from_js:
  11.             data = json.loads(result_from_js.replace("'{","{").replace("}'","}"))
  12.             print(f"JS返回的数据是{data}")
  13.         else:
  14.             print("JS没有返回数据")
复制代码
可以看到,不管是同步、还是异步;最重要的是js代码的编写;如果你熟悉js代码;那么你将会事半功倍;


来源:程序园用户自行投稿发布,如果侵权,请联系站长删除
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!
您需要登录后才可以回帖 登录 | 立即注册