包含 AJAX 按钮的屏幕抓取网页
Screen scraping web page containing button with AJAX
我正在尝试使我们的一些流程自动化,一个包括登录到外部网页,单击 link 展开详细信息,然后获取显示的所有详细信息。
我已经登录了进程,展开后可以抓取所有详细信息。
问题在于单击 link。 link 的定义如下(我已经删除了 Submit
方法实际执行的操作,因为代码很长并且可能不相关。显然 img
是占位符,只是作为示例):
<a id="form:SummarySubView:closedToggleControl" onclick="A4J.AJAX.Submit(...); return false;" href="#">
<img ... />
</a>
我使用以下数据:
void browser_DocumentCompleted(object sender, WebBrowserDocumentCompletedEventArgs e)
{
WebBrowser browser = (WebBrowser)sender;
HtmlElement expandDetails = browser.Document.GetElementById("form:SummarySubView:closedToggleControl");
//When open ID for element is "form:SummarySubView:openToggleControl"
if(expandDetails == null) //If already expanded
{
//Stuff
}
else
{
expandDetails.InvokeMember("click"); //Click on element to run AJAX
}
}
运行 expandDetails.InvokeMember("click");
browser_DocumentCompleted
按预期再次调用,但文档与之前相同,并且再次找到 expandDetails
id 为 "closed" .这意味着我要查找的详细信息永远不会显示。
如何在 AJAX 脚本正确运行后访问文档?
添加 Timer
以延迟检查文档似乎没有用。
好的,首先,document.complete 事件将为页面中的所有框架触发。因此,如果您有 5 个 Iframe,您将获得 6 个文档完成事件。
所以你需要检查一下你是否真的是顶级window。
单独执行此操作可能会解决您的问题。
private void WebBrowser1_DocumentCompleted(object sender, WebBrowserDocumentCompletedEventArgs e)
{
WebBrowser wb = sender as WebBrowser;
//check to make sure we are on the TOP-level page.
if (wb.Document.Window.Parent == null)
{
//do whatever else you need to here
}
}
如果还是不行,您可以使用计时器在文档完成后等待几秒钟。
public partial class Form1 : Form
{
Timer t;
public Form1()
{
InitializeComponent();
webBrowser1.DocumentCompleted += WebBrowser1_DocumentCompleted;
}
private void WebBrowser1_DocumentCompleted(object sender, WebBrowserDocumentCompletedEventArgs e)
{
WebBrowser wb = sender as WebBrowser;
//check to make sure we are on the TOP-level page.
if (wb.Document.Window.Parent == null)
{
t = new Timer();
t.Tick += (Timersender, eventargs) =>
{
//do whatever else you need to here
t.Stop();
};
t.Interval = 2000; //wait 2 seconds for the document to complete
t.Start();
}
}
}
您可以根据需要将计时器调整得更长或更短。但这应该能满足您的需求。
一个非常简单的解决方案似乎奏效了。我的代码现在看起来像:
void browser_DocumentCompleted(object sender, WebBrowserDocumentCompletedEventArgs e)
{
WebBrowser browser = (WebBrowser)sender;
HtmlElement expandDetails = browser.Document.GetElementById("form:SummarySubView:closedToggleControl");
//When open ID for element is "form:SummarySubView:openToggleControl"
if(expandDetails == null) //If already expanded
{
//Stuff
}
else
{
expandDetails.InvokeMember("click"); //Click on element to run AJAX
while (expandDetails != null)
{
expandDetails = browser.Document.GetElementById("form:SummarySubView0:closedToggleControl");
Application.DoEvents();
System.Threading.Thread.Sleep(200);
}
//Stuff
}
}
所以 运行 while
循环对我来说工作正常。
我正在尝试使我们的一些流程自动化,一个包括登录到外部网页,单击 link 展开详细信息,然后获取显示的所有详细信息。
我已经登录了进程,展开后可以抓取所有详细信息。
问题在于单击 link。 link 的定义如下(我已经删除了 Submit
方法实际执行的操作,因为代码很长并且可能不相关。显然 img
是占位符,只是作为示例):
<a id="form:SummarySubView:closedToggleControl" onclick="A4J.AJAX.Submit(...); return false;" href="#">
<img ... />
</a>
我使用以下数据:
void browser_DocumentCompleted(object sender, WebBrowserDocumentCompletedEventArgs e)
{
WebBrowser browser = (WebBrowser)sender;
HtmlElement expandDetails = browser.Document.GetElementById("form:SummarySubView:closedToggleControl");
//When open ID for element is "form:SummarySubView:openToggleControl"
if(expandDetails == null) //If already expanded
{
//Stuff
}
else
{
expandDetails.InvokeMember("click"); //Click on element to run AJAX
}
}
运行 expandDetails.InvokeMember("click");
browser_DocumentCompleted
按预期再次调用,但文档与之前相同,并且再次找到 expandDetails
id 为 "closed" .这意味着我要查找的详细信息永远不会显示。
如何在 AJAX 脚本正确运行后访问文档?
添加 Timer
以延迟检查文档似乎没有用。
好的,首先,document.complete 事件将为页面中的所有框架触发。因此,如果您有 5 个 Iframe,您将获得 6 个文档完成事件。
所以你需要检查一下你是否真的是顶级window。 单独执行此操作可能会解决您的问题。
private void WebBrowser1_DocumentCompleted(object sender, WebBrowserDocumentCompletedEventArgs e)
{
WebBrowser wb = sender as WebBrowser;
//check to make sure we are on the TOP-level page.
if (wb.Document.Window.Parent == null)
{
//do whatever else you need to here
}
}
如果还是不行,您可以使用计时器在文档完成后等待几秒钟。
public partial class Form1 : Form
{
Timer t;
public Form1()
{
InitializeComponent();
webBrowser1.DocumentCompleted += WebBrowser1_DocumentCompleted;
}
private void WebBrowser1_DocumentCompleted(object sender, WebBrowserDocumentCompletedEventArgs e)
{
WebBrowser wb = sender as WebBrowser;
//check to make sure we are on the TOP-level page.
if (wb.Document.Window.Parent == null)
{
t = new Timer();
t.Tick += (Timersender, eventargs) =>
{
//do whatever else you need to here
t.Stop();
};
t.Interval = 2000; //wait 2 seconds for the document to complete
t.Start();
}
}
}
您可以根据需要将计时器调整得更长或更短。但这应该能满足您的需求。
一个非常简单的解决方案似乎奏效了。我的代码现在看起来像:
void browser_DocumentCompleted(object sender, WebBrowserDocumentCompletedEventArgs e)
{
WebBrowser browser = (WebBrowser)sender;
HtmlElement expandDetails = browser.Document.GetElementById("form:SummarySubView:closedToggleControl");
//When open ID for element is "form:SummarySubView:openToggleControl"
if(expandDetails == null) //If already expanded
{
//Stuff
}
else
{
expandDetails.InvokeMember("click"); //Click on element to run AJAX
while (expandDetails != null)
{
expandDetails = browser.Document.GetElementById("form:SummarySubView0:closedToggleControl");
Application.DoEvents();
System.Threading.Thread.Sleep(200);
}
//Stuff
}
}
所以 运行 while
循环对我来说工作正常。