使用Selenium和Python执行异步Fetch请求并获取响应

聖光之護
发布: 2025-11-01 11:46:06
原创
388人浏览过

使用selenium和python执行异步fetch请求并获取响应

本文详细介绍了如何利用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数据时,会遇到一些挑战。

Selenium中Fetch请求的挑战

直接使用driver.execute_script()执行fetch请求时,由于fetch是一个异步操作,它会立即返回一个JavaScript Promise对象,而不是请求的实际数据。这意味着Python端无法直接获取到Promise解析后的结果。为了解决这一问题,我们需要利用Selenium提供的异步脚本执行机制。

核心解决方案:execute_async_script

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响应。

AppMall应用商店
AppMall应用商店

AI应用商店,提供即时交付、按需付费的人工智能应用服务

AppMall应用商店56
查看详情 AppMall应用商店

1. Python环境准备与WebDriver初始化

首先,我们需要导入必要的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.")
登录后复制

2. 执行异步Fetch请求(GET示例)

我们将构建一个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}")
登录后复制

3. 执行异步Fetch请求(POST示例)

接着,我们演示如何发送一个带有请求体的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.")
登录后复制

代码解析

  • *`driver.execute_async_script(js_script, args)**: 这是核心方法。js_script是将在浏览器中执行的JavaScript代码。*args是传递给JavaScript脚本的参数。在JavaScript中,这些参数通过arguments[0],arguments[1]等访问。arguments[0]`总是Selenium注入的回调函数。
  • JavaScript fetch API:
    • fetch(url, options): 发送HTTP请求。
    • options.method: 指定HTTP方法,如'GET'或'POST'。
    • options.headers: 一个包含请求头的JavaScript对象。键值对对应HTTP头名称和值。
    • options.body: 对于POST等请求,用于发送请求体。如果发送JSON数据,需要使用JSON.stringify()将其转换为字符串。
  • Promise链式调用:
    • .then(response => ...): 处理fetch返回的响应对象。
    • response.ok: 检查响应状态码是否在200-299之间。
    • response.json() / response.text(): 将响应体解析为JSON对象或纯文本。这些也是异步操作,返回Promise。
    • .then(data => callback(data)): 在数据成功解析后,通过callback函数将数据返回给Python。
    • .catch(error => callback({ error: error.message })): 捕获fetch或响应处理过程中的任何错误,并将错误信息返回给Python。

注意事项

  1. 代理设置的局限性: 虽然可以在ChromeOptions中设置浏览器级代理,但通过execute_async_script直接发起的fetch请求,有时可能不会完全遵循这些代理设置。这取决于浏览器内部的实现和fetch API的行为。如果代理是关键,可能需要考虑在fetch请求中直接配置代理(如果API支持,但标准fetch不支持直接配置代理),或者使用其他网络拦截工具(如Selenium Wire)来捕获和修改请求。
  2. 数据类型转换: JavaScript通过callback返回的数据会由Selenium自动转换为Python类型。例如,JavaScript对象会被转换为Python字典,数组转换为列表,字符串转换为字符串。确保JavaScript返回的数据结构与Python期望的匹配。
  3. 超时处理: execute_async_script默认的超时时间可能很短或为0。务必使用driver.set_script_timeout()来设置一个合理的超时时间,以避免因网络延迟或脚本执行时间过长而导致的TimeoutException。
  4. 错误处理: 在JavaScript脚本中加入.catch()块是非常重要的,这样即使fetch请求失败或响应处理出错,Python也能接收到错误信息,而不是脚本挂起或抛出未捕获的异常。
  5. 跨域请求 (CORS): 如果fetch请求的目标URL与当前页面的源不同,可能会遇到CORS问题。确保服务器端已正确配置CORS策略以允许这些请求。

总结

通过execute_async_script方法,Selenium为我们提供了一个强大的机制,可以在浏览器环境中执行异步JavaScript代码,特别是像fetch这样的网络请求。这使得我们能够灵活地发送带有自定义HTTP头的GET或POST请求,并无缝地将异步响应数据检索到Python程序中进行进一步处理。理解其工作原理和注意事项,将有助于更高效地利用Selenium解决复杂的Web自动化任务。

以上就是使用Selenium和Python执行异步Fetch请求并获取响应的详细内容,更多请关注php中文网其它相关文章!

最佳 Windows 性能的顶级免费优化软件
最佳 Windows 性能的顶级免费优化软件

每个人都需要一台速度更快、更稳定的 PC。随着时间的推移,垃圾文件、旧注册表数据和不必要的后台进程会占用资源并降低性能。幸运的是,许多工具可以让 Windows 保持平稳运行。

下载
来源:php中文网
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn
最新问题
开源免费商场系统广告
热门教程
更多>
最新下载
更多>
网站特效
网站源码
网站素材
前端模板
关于我们 免责申明 意见反馈 讲师合作 广告合作 最新更新 English
php中文网:公益在线php培训,帮助PHP学习者快速成长!
关注服务号 技术交流群
PHP中文网订阅号
每天精选资源文章推送
PHP中文网APP
随时随地碎片化学习
PHP中文网抖音号
发现有趣的

Copyright 2014-2025 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号