selenium C#等待后台请求(不是由c#代码发起)

selenium C# wait for background requests(not initiated by c# code)

我正在使用 selenium chrome 驱动程序结合 cefsharp,我正在处理的页面会在每次单击元素时发送某种 ping 请求(fetch/xhr)问题是这些请求不是由 selenium chrome 驱动程序发起,所以我无法跟踪它们并等待完成。 selenium 或 js 有什么方法可以跟踪这些请求吗?

使用 Selenium 4,您实际上可以 intercept requests

调用 Enable 开始请求跟踪

调用WaitForRequestResponse等待具体请求

如果您可以使用相同的请求,您可以使用 Clear

清除已经捕获的请求
    public class WebDriverNetworkController
    {
        private const string RequestWillBeSent = "requestWillBeSent";
        private const string ResponseReceived = "responseReceived";

        private readonly IDriverProvider _driverProvider;
        private readonly ILogger _log;
        private readonly ConcurrentDictionary<DevToolsSession, List<HttpRequestModel>> _sentRequests = new();

        public WebDriverNetworkController(IDriverProvider driverProvider, ILogger log)
        {
            _driverProvider = driverProvider;
            _log = log;
        }

        private void HandleDevToolsEvent(object sender, DevToolsEventReceivedEventArgs e)
        {
            var session = sender as DevToolsSession;
            switch (e.EventName)
            {
                case RequestWillBeSent:
                {
                    OnRequestWillBeSent(session, e.EventData);
                    break;
                }

                case ResponseReceived:
                {
                    OnResponseReceived(session, e.EventData);
                    break;
                }
            }
        }

        public void Enable()
        {
            _log.Information("Enabling network tracing");
            var session = GetDevToolsSession();
            session.DevToolsEventReceived += HandleDevToolsEvent;

            var enableTask = session.Domains.Network.EnableNetwork();
            enableTask.Wait();
        }

        public void Disable()
        {
            _log.Information("Disabling network tracing");
            var session = GetDevToolsSession();
            session.DevToolsEventReceived -= HandleDevToolsEvent;

            var disableTask = session.Domains.Network.DisableNetwork();
            disableTask.Wait();
        }

        public void Clear()
        {
            _log.Information("Clearing captured network tracing requests");
            var sentRequests = GetRequests();
            sentRequests.Clear();
        }

        public HttpRequestModel[] GetAllRequests() => GetRequests().ToArray();

        public HttpRequestModel WaitForRequestResponse(HttpMethod method, string uri)
        {
            _log.Debug($"Waiting for {method.Method} request to {uri}");
            var session = GetDevToolsSession();

            HttpRequestModel request = null;
            var waiter = new ConditionWaiter
            {
                Message = $"{method.Method} request to {uri}"
            };
            waiter.Until(() =>
            {
                request = GetLastSentRequest(method, uri, session);
                return request?.Response != null;
            });

            return request;
        }

        private HttpRequestModel GetLastSentRequest(HttpMethod method, string uri, DevToolsSession session) =>
            GetRequests(session).LastOrDefault(request => request.Method == method && request.Uri.EndsWith(uri));

        private DevToolsSession GetDevToolsSession()
        {
            var driver = _driverProvider.GetDriver();
            if (driver is IDevTools devTools)
            {
                return devTools.GetDevToolsSession();
            }

            throw new WebDriverException($"Could not cast {driver.GetType().Name} to {nameof(IDevTools)}");
        }

        private List<HttpRequestModel> GetRequests(DevToolsSession session = null) =>
            _sentRequests.GetOrAdd(session ?? GetDevToolsSession(), _ => new());

        private void OnRequestWillBeSent(DevToolsSession session, JToken eventData)
        {
            var requestModel = new HttpRequestModel
            {
                Id = eventData.SelectToken("requestId", true)!.Value<string>(),
                Method = new(eventData.SelectToken("request.method", true)!.Value<string>()!),
                Uri = eventData.SelectToken("request.url", true)!.Value<string>(),
                Body = eventData.SelectToken("request")!.Value<string>("postData")
            };
            var sentRequests = _sentRequests.GetOrAdd(session, _ => new());
            sentRequests.Add(requestModel);
        }

        private void OnResponseReceived(DevToolsSession session, JToken eventData)
        {
            var requestId = eventData.SelectToken("requestId", true)!.Value<string>();
            var responseModel = new HttpResponseModel
            {
                Uri = eventData.SelectToken("response.url", true)!.Value<string>(),
                StatusCode = (HttpStatusCode)eventData.SelectToken("response.status", true)!.Value<long>()
            };
            var sentRequests = _sentRequests[session];
            var request = sentRequests.Last(request => request.Id == requestId);
            request.Response = responseModel;
        }
    }

上面的代码不能立即使用,但应该可以让您大致了解该方法。