如何在Web浏览器中单击多个页面上的多个链接

时间:2011-09-12 12:08:36

标签: c# web

Iam过去一周无法做到这一点。我想在C#中使用webBrowser点击多个网页的多个链接以下是代码,请在这方面帮助我。

public void DoDelete()
{
    int count = 0;

    if (corruptList.Count > 0)
    {
        foreach (string listItem in corruptList)
        {
            var th = new Thread(() =>
            {
                try
                {
                    WebBrowser webBrowser = new WebBrowser();
                    webBrowser.DocumentCompleted += new WebBrowserDocumentCompletedEventHandler(webBroswer_DocumentCompleted);
                    webBrowser.Navigate(listItem);
                    Thread.Sleep(100);
                    webBrowser.Dispose();
                }
                catch (Exception ex)
                {
                    throw ex;
                }
                this.Invoke(new MethodInvoker(delegate
                {
                    dataGridView_CorruptLinks.Rows[count].Cells[2].Value = "Deleted";
                }));
            });
            th.SetApartmentState(ApartmentState.STA);
            th.Start();
            Thread.Sleep(100);
        }
        count++;
    }
}


void webBroswer_DocumentCompleted(object sender, WebBrowserDocumentCompletedEventArgs e)
{
    try
    {
        WebBrowser webBrowser = sender as WebBrowser;
        HtmlElementCollection ec = webBrowser.Document.GetElementsByTagName("a");
        foreach (HtmlElement item in ec)
        {
            if (item.InnerHtml == "Delete this invalid field")
            {
                item.InvokeMember("Click");
                break;
            }
        }
    }
    catch (Exception exp)
    {
    }
}

3 个答案:

答案 0 :(得分:0)

您可以使用以下内容访问WebBrowser文档内容(您缺少正文并需要将文档键入动态)。

dynamic doc = browser.Document;
var button = doc.body.document.getElementById("button");
button.Click();

答案 1 :(得分:0)

Navigate是一个异步操作,您只需要在Web浏览器对象上调用Dispose之前完成1/10秒。您的导航和点击可能需要比完成时间更长的时间,因此没有Web浏览器可以采取行动......您还“吞下”文档完整处理程序中的所有异常。这是一件非常糟糕的事情。你至少应该在那里做一些调试记录来帮助你自己诊断问题。

但是,为了保持类似的逻辑,你应该在类级别创建一组Web浏览器。类似的东西:

private List<WebBrowser> _myWebBrowsers;

然后在循环中添加到此列表但不调用Dispose。只有在完成后才能丢弃浏览器。

尽管您的代码存在其他一些潜在问题,但这应该会让您更接近。您每次通过循环分配一个borser对象和线程。这很快就会变得笨拙。您应该使用线程管理机制来限制此过程。

简化课程:

class WebRunner
{
    private List<string> _corruptList = new List<string>();
    private List<WebBrowser> _browsers = new List<WebBrowser>();

    public void Run()
    {
        _corruptList.Add("http://google.com");
        _corruptList.Add("http://yahoo.com");
        _corruptList.Add("http://bing.com");

        DoDelete();

        Console.ReadKey();
    }

    public void DoDelete()
    {
        if (_corruptList.Count < 1) return;

        int counter = 1;

        foreach (string listItem in _corruptList)
        {
            WebBrowser webBrowser = new WebBrowser();
            _browsers.Add(webBrowser);
            webBrowser.DocumentCompleted += new WebBrowserDocumentCompletedEventHandler(webBroswer_DocumentCompleted);
            webBrowser.Navigated += new WebBrowserNavigatedEventHandler(webBrowser_Navigated);
            webBrowser.Navigate(listItem);
            if (counter % 10 == 0) Thread.Sleep(3000); // let app catch up every so often
            counter++;
        }
    }

    void webBrowser_Navigated(object sender, WebBrowserNavigatedEventArgs e)
    {
        Console.WriteLine("NAVIGATED: " + e.Url);
    }

    void webBroswer_DocumentCompleted(object sender, WebBrowserDocumentCompletedEventArgs e)
    {
        Console.WriteLine("COMPLETED!");
        try
        {
            WebBrowser webBrowser = sender as WebBrowser;

            HtmlDocument doc = webBrowser.Document;
            var button = doc.Body.Document.GetElementById("button");
            button.InvokeMember("Click");

            _browsers.Remove(webBrowser);
        }
        catch (Exception exp)
        {
            Console.WriteLine(exp.StackTrace);
            MessageBox.Show(exp.Message);
        }
    }
}

答案 2 :(得分:0)

我第二天就找到了解决方案。通过在thread.sleep()之后放置语句逐个处理线程,对不起发帖  if(th.ThreadState == ThreadState.Aborted || th.ThreadState == ThreadState.Stopped)