
本文详细介绍了如何利用Selenium的`execute_async_script`方法在Python中执行JavaScript的`fetch`请求,并高效地获取其异步响应。内容涵盖了设置自定义HTTP头、处理GET/POST请求以及从浏览器环境无缝检索数据到Python的实用技巧。
在自动化测试和网页抓取场景中,我们经常需要模拟浏览器行为来发送HTTP请求,并获取响应数据。Selenium作为一款强大的浏览器自动化工具,通常通过模拟用户操作来与页面交互。然而,当需要直接在浏览器环境中执行JavaScript的fetch API来发送具有自定义HTTP头(如CUSTOM_HEADER_1、CUSTOM_HEADER_2等)的GET或POST请求,并获取其异步返回的JSON数据时,会遇到一些挑战。
直接使用driver.execute_script()执行fetch请求时,由于fetch是一个异步操作,它会立即返回一个JavaScript Promise对象,而不是请求的实际数据。这意味着Python端无法直接获取到Promise解析后的结果。为了解决这一问题,我们需要利用Selenium提供的异步脚本执行机制。
Selenium的execute_async_script()方法专门用于执行异步JavaScript代码。它允许JavaScript代码在完成其异步操作后,通过调用一个特殊的callback函数将结果返回给Python。这是处理fetch请求异步特性的关键。
立即学习“Python免费学习笔记(深入)”;
当execute_async_script()被调用时,它会向JavaScript环境注入一个回调函数作为其第一个参数(通常命名为arguments[0])。JavaScript代码在执行fetch请求并处理完响应后,只需将最终结果作为参数传递给这个callback函数,Selenium就会等待该回调被执行,并将传递给回调函数的值作为execute_async_script()的返回值返回给Python。
下面我们将通过一个完整的Python示例,演示如何使用execute_async_script来执行带有自定义头的GET和POST fetch请求,并获取JSON响应。
首先,我们需要导入必要的Selenium模块,并配置WebDriver。这里以Chrome为例,并展示如何尝试配置代理(尽管需要注意其对fetch请求的潜在局限性)。
from selenium import webdriver
from selenium.webdriver.chrome.options import Options
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
from selenium.common.exceptions import TimeoutException
import json
# 示例代理设置 (注意:对于execute_async_script发起的fetch,此设置可能不总是生效)
# 如果fetch请求需要通过代理,通常需要更复杂的网络拦截或直接在fetch选项中指定代理
proxy_server_url = "127.0.0.1:8888"
chrome_options = webdriver.ChromeOptions()
# chrome_options.add_argument('--proxy-server=%s' % proxy_server_url)
chrome_options.add_argument("ignore-certificate-errors")
chrome_options.add_argument("--headless") # 可选:无头模式运行
driver = webdriver.Chrome(options=chrome_options)
# 设置异步脚本的超时时间,默认为0,需要手动设置
driver.set_script_timeout(10) # 设置为10秒
# 导航到一个空白页或任意页面,以确保浏览器环境已准备好执行JS
driver.get("about:blank")
print("WebDriver initialized and navigated to about:blank.")我们将构建一个JavaScript脚本,用于执行GET请求,并期望返回JSON数据。
# 示例:GET请求,获取JSON数据
get_url = "https://jsonplaceholder.typicode.com/posts/1" # 示例URL
get_headers = {
"Accept": "application/json",
"Custom-Header-GET": "get_value_123"
}
# 构建JavaScript fetch请求脚本
js_script_get = """
let callback = arguments[0]; // Selenium注入的回调函数
let url = arguments[1];
let headers = arguments[2];
fetch(url, {
method: 'GET',
headers: headers
})
.then(response => {
if (!response.ok) {
// 如果响应状态码不是2xx,抛出错误
return response.text().then(text => { throw new Error(`Network response was not ok: ${response.status} - ${text}`); });
}
return response.json(); // 尝试解析为JSON
})
.then(data => callback(data)) // 将解析后的数据通过回调返回给Python
.catch(error => callback({ error: error.message })); // 捕获错误并返回错误信息
"""
print(f"\nExecuting GET request to: {get_url}")
try:
response_data_get = driver.execute_async_script(js_script_get, get_url, get_headers)
print("GET Request Response (Python):")
print(json.dumps(response_data_get, indent=2, ensure_ascii=False))
except TimeoutException:
print("GET request timed out.")
except Exception as e:
print(f"An error occurred during GET request: {e}")接着,我们演示如何发送一个带有请求体的POST请求。
# 示例:POST请求,发送JSON数据
post_url = "https://jsonplaceholder.typicode.com/posts" # 示例URL
post_data = {"title": "foo", "body": "bar", "userId": 1}
post_headers = {
"Content-Type": "application/json",
"Accept": "application/json",
"Custom-Header-POST": "post_value_456"
}
# 构建JavaScript fetch请求脚本
js_script_post = """
let callback = arguments[0];
let url = arguments[1];
let headers = arguments[2];
let body = arguments[3];
fetch(url, {
method: 'POST',
headers: headers,
body: JSON.stringify(body) // 将POST数据转换为JSON字符串
})
.then(response => {
if (!response.ok) {
return response.text().then(text => { throw new Error(`Network response was not ok: ${response.status} - ${text}`); });
}
return response.json();
})
.then(data => callback(data))
.catch(error => callback({ error: error.message }));
"""
print(f"\nExecuting POST request to: {post_url}")
try:
response_data_post = driver.execute_async_script(js_script_post, post_url, post_headers, post_data)
print("POST Request Response (Python):")
print(json.dumps(response_data_post, indent=2, ensure_ascii=False))
except TimeoutException:
print("POST request timed out.")
except Exception as e:
print(f"An error occurred during POST request: {e}")
# 完成后关闭WebDriver
driver.quit()
print("\nWebDriver closed.")通过execute_async_script方法,Selenium为我们提供了一个强大的机制,可以在浏览器环境中执行异步JavaScript代码,特别是像fetch这样的网络请求。这使得我们能够灵活地发送带有自定义HTTP头的GET或POST请求,并无缝地将异步响应数据检索到Python程序中进行进一步处理。理解其工作原理和注意事项,将有助于更高效地利用Selenium解决复杂的Web自动化任务。
以上就是使用Selenium和Python执行异步Fetch请求并获取响应的详细内容,更多请关注php中文网其它相关文章!
每个人都需要一台速度更快、更稳定的 PC。随着时间的推移,垃圾文件、旧注册表数据和不必要的后台进程会占用资源并降低性能。幸运的是,许多工具可以让 Windows 保持平稳运行。
Copyright 2014-2025 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号