我需要通过编程在网站上做3个动作
(在此之后,出现一个请求,页面返回搜索结果)
如果我把动作1和2放在按钮1中:
private void Button1_Click(object sender, EventArgs e)
{
string jsScript1 = "document.getElementById('story').value=" + '\'' + textFind.Text + '\'' + ";"
+ "document.querySelector('body > div.wrapper > div.header > div.header44 > div.search_panel > span > form > button').click();";
var task1 = chrome.EvaluateScriptAsync(jsScript1);
task1.Wait();
}
和按钮2中的行动3:
private void Button2_Click(object sender, EventArgs e)
{
string jsScript3 = "document.getElementsByTagName('a')[1].click();";
var task3 = chrome.EvaluateScriptAsync(jsScript3);
task3.Wait();
}
一切都很完美。但我想在一个按钮里做所有这些动作。
我找到了以下解决方案:
private async void ButtonFind_Click(object sender, EventArgs e)
{
//Action 1 & 2
string jsScript1 = "document.getElementById('story').value=" + '\'' + textFind.Text + '\'' + ";"
+ "document.querySelector('body > div.wrapper > div.header > div.header44 > div.search_panel > span > form > button').click();";
await chrome.EvaluateScriptAsync(jsScript1);
//Action3
Thread.Sleep(1000); //it is necessary to set exactly 1 seconds
string jsScript3 = "document.getElementsByTagName('a')[2].click();";
await chrome.EvaluateScriptAsync(jsScript3);
}
我必须使用Thread.Sleep(1000);
,因为在JavaScript中,重定向或单击搜索按钮会破坏当前在浏览器中运行的所有脚本。但我认为使用Thread.Sleep或Task.Delay不是一个好主意。否则,我如何才能不使用Thread.休眠/Task.Delay来更改代码?
发布于 2022-04-23 09:10:04
您可以使用以下内容来等待页面加载
// create a static class for the extension method
public static Task<LoadUrlAsyncResponse> WaitForLoadAsync(this IWebBrowser browser)
{
var tcs = new TaskCompletionSource<LoadUrlAsyncResponse>(TaskCreationOptions.RunContinuationsAsynchronously);
EventHandler<LoadErrorEventArgs> loadErrorHandler = null;
EventHandler<LoadingStateChangedEventArgs> loadingStateChangeHandler = null;
loadErrorHandler = (sender, args) =>
{
//Actions that trigger a download will raise an aborted error.
//Generally speaking Aborted is safe to ignore
if (args.ErrorCode == CefErrorCode.Aborted)
{
return;
}
//If LoadError was called then we'll remove both our handlers
//as we won't need to capture LoadingStateChanged, we know there
//was an error
browser.LoadError -= loadErrorHandler;
browser.LoadingStateChanged -= loadingStateChangeHandler;
tcs.TrySetResult(new LoadUrlAsyncResponse(args.ErrorCode, -1));
};
loadingStateChangeHandler = (sender, args) =>
{
//Wait for while page to finish loading not just the first frame
if (!args.IsLoading)
{
browser.LoadError -= loadErrorHandler;
browser.LoadingStateChanged -= loadingStateChangeHandler;
var host = args.Browser.GetHost();
var navEntry = host?.GetVisibleNavigationEntry();
int statusCode = navEntry?.HttpStatusCode ?? -1;
//By default 0 is some sort of error, we map that to -1
//so that it's clearer that something failed.
if (statusCode == 0)
{
statusCode = -1;
}
tcs.TrySetResult(new LoadUrlAsyncResponse(statusCode == -1 ? CefErrorCode.Failed : CefErrorCode.None, statusCode));
}
};
browser.LoadingStateChanged += loadingStateChangeHandler;
browser.LoadError += loadErrorHandler;
return tcs.Task;
}
// usage example
await Task.WhenAll(chrome.WaitForLoadAsync(), chrome.EvaluateScriptAsync(script));
发布于 2022-04-26 09:16:08
你绝不能以这种方式使用睡眠。Web可能会花费更多的时间或更少的时间,而您的代码在一段时间内就会失败。您必须始终在异步模式下工作。如果需要,您可以在出现错误的情况下放置超时,但在正常模式下,请始终等到得到所需的超时。
例如,单击该按钮并设置计时器以等待链接的出现。然后,导航到第一个链接。
在其他情况下,当出现真正的导航而丢失JavaScript上下文时,可以使用绑定对象将C#应用程序和浏览器组合在一起。这样做,您可以从您的JavaScript查询您在做什么,并从JavaScript向您的C#代码提供反馈。这是坚持国家的一种方式。
一个典型的示例是,当您填写一些表单并单击“继续”,继续.在几页中导航。如果要收集所有信息,则需要绑定对象。我将它与json序列化一起使用来管理更复杂的数据。
如果您要在浏览器中进行大量工作,我建议您将自己的脚本插入到您导航的页面中。在此表单中,您可以在加载的页面中使用您自己的类。
https://stackoverflow.com/questions/71977392
复制相似问题