包含 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 循环对我来说工作正常。