我想提取某个网站的一个子页面的一个字符串,是IP地址来的。
但是访问那个网站要先登录。
网站是局域网,外网无法访问,抱歉。
所以我先做了一个自动填表的小程序。
现在遇到几个问题如下:1.自动点击确定安全证书
使用webBrowser.Navigate定位到网站时会弹出安全证书,上面有三个按钮“是”“否”“详细信息”,我想让它自动点击“是”应该怎么做呢?
点击“登陆”后还会弹出一个“安全信息”对话框,也有上面三个按钮,想让它自动点击“是”,这样才能成功登陆。2.判断页面加载完成
一般情况下可以用webBrowser1_DocumentCompleted方法,但是我发现程序只在定位到第一个URL时调用webBrowser1_DocumentCompleted,如果我登陆后想webBrowser.Navigate跳转到另一个子页面,就没有调用webBrowser1_DocumentCompleted了。然后读取网页文档内容就会出现空对象的问题。
我的代码如下:    public partial class Form1 : Form
    {
        bool isload = false;
        public Form1()
        {
            InitializeComponent();
            webBrowser1.Navigate(url1);//第一个页面
        }
        private void Form1_Load(object sender, EventArgs e)
        {
        }        private void button1_Click_1(object sender, EventArgs e)
        {
            HtmlElement element = webBrowser1.Document.GetElementById("username");
            element.InnerText = "07lls";
            element = webBrowser1.Document.GetElementById("password");
            element.InnerText = "1";
            webBrowser1.Document.GetElementById("image").InvokeMember("Click");            //this.webBrowser1_DocumentCompleted(null ,null);
            if (isload)
            {
                isload = false;
                webBrowser1.Navigate(url2);//跳到第二个页面
            }
            //this.webBrowser1_DocumentCompleted(null, null);
            if (isload )
            {
                isload = false;
                HtmlElement temp = webBrowser1.Document.GetElementById("LogonHistory1_dgResult");
                //System.Threading.Thread.Sleep(10000);
                MessageBox.Show(temp.ToString());                
            }
        }
        private void webBrowser1_DocumentCompleted(object sender, WebBrowserDocumentCompletedEventArgs e)
        {
            isload = true;
        }
    }
}3.如何提取网页的内容
第二个页面的源文件如下:
==============================================
<FONT face="宋体">
<table cellspacing="0" rules="all" border="1" id="LogonHistory1_dgResult" style="border-width:1px;border-style:solid;font-size:X-Small;width:100%;border-collapse:collapse;">
<tr class="tableTag" nowrap="nowrap" align="Center">
<td nowrap="nowrap"><a href="javascript:__doPostBack('LogonHistory1$dgResult$_ctl2$_ctl0','')">登录IP</a></td><td nowrap="nowrap"><a href="javascript:__doPostBack('LogonHistory1$dgResult$_ctl2$_ctl1','')">登录时间</a></td><td nowrap="nowrap"><a href="javascript:__doPostBack('LogonHistory1$dgResult$_ctl2$_ctl2','')">登出时间</a></td><td nowrap="nowrap"><a href="javascript:__doPostBack('LogonHistory1$dgResult$_ctl2$_ctl4','')">在线时间</a></td><td nowrap="nowrap"><a href="javascript:__doPostBack('LogonHistory1$dgResult$_ctl2$_ctl5','')">国内流量</a></td><td nowrap="nowrap"><a href="javascript:__doPostBack('LogonHistory1$dgResult$_ctl2$_ctl6','')">国际流量</a></td>
</tr><tr nowrap="nowrap" align="Center" style="background-color:White;height:25px;">
<td>10.18.2.10</td><td nowrap="nowrap" align="Left">2010-1-27 9:15:32</td><td nowrap="nowrap" align="Left">&nbsp;</td><td nowrap="nowrap" align="Right">0:12'36"</td><td nowrap="nowrap" align="Right">0.02 M </td><td nowrap="nowrap" align="Right">0 M </td>
</tr><tr nowrap="nowrap" align="Center" style="background-color:#F7F7F7;height:25px;">
<td>10.18.2.10</td><td nowrap="nowrap" align="Left">2010-1-27 8:49:26</td><td nowrap="nowrap" align="Left">2010-1-27 9:14:35</td><td nowrap="nowrap" align="Right">0:25'09"</td><td nowrap="nowrap" align="Right">4 M </td><td nowrap="nowrap" align="Right">0 M </td>
</tr><tr nowrap="nowrap" align="Center" style="background-color:White;height:25px;">
<td>10.184.2.10</td><td nowrap="nowrap" align="Left">2010-1-26 18:45:34</td><td nowrap="nowrap" align="Left">2010-1-26 23:40:51</td><td nowrap="nowrap" align="Right">4:55'17"</td><td nowrap="nowrap" align="Right">40.92 M </td><td nowrap="nowrap" align="Right">0 M </td>
......
==============================================如果我想找出第一个IP地址,上面是第一个“10.18.2.10”,应该怎么做呢?
如果用webBrowser.Document.GetElementById("");引号内应该填什么元素名?问题较多,分数较少,请见谅!
谢谢回答!

解决方案 »

  1.   

     2:.........private void webBrowser_DocumentCompleted(object sender, WebBrowserDocumentCompletedEventArgs e)
            {
                if (webBrowser1.ReadyState == WebBrowserReadyState.Complete)
                {
                    //完成
                }
            }
      

  2.   

    这个问题的难点就在于10.18.2.10 两边没有可区别的tag
    且10.18.2.10 这个字符串也不好判断可以考虑将页面中所有<td></td>之间的字符串取出,放入一个数组,
    然后遍历数组,将每一个按 “.” split一下,判断aplit后的是否长度是4,并且全是<=3位的数字。
    这中情况下出错的概率应该可以忽略不计了。
      

  3.   


    这方法似乎行得通
    那么我应该用什么语句把所有的<td> </td>之间的字符串取出来呢?谢谢
      

  4.   

    取第一个<td> 和 之后的第一个</td>之间的就好了,截取或者正则
      

  5.   

      string Html = "<FONT face=\"宋体\"> <table cellspacing=\"0\" rules=\"all\" border=\"1\" id=\"LogonHistory1_dgResult\" style=\"border-width:1px;border-style:solid;font-size:X-Small;width:100%;border-collapse:collapse;\"> <tr class=\"tableTag\" nowrap=\nowrap\" align=\"Center\"> <td nowrap=\"nowrap\"> <a href=\"javascript:__doPostBack('LogonHistory1$dgResult$_ctl2$_ctl0','')\">登录IP </a> </td> <td nowrap=\"nowrap\"> <a href=\"javascript:__doPostBack('LogonHistory1$dgResult$_ctl2$_ctl1','')\">登录时间 </a> </td> <td nowrap=\"nowrap\"> <a href=\"javascript:__doPostBack('LogonHistory1$dgResult$_ctl2$_ctl2','')\">登出时间 </a> </td> <td nowrap=\"nowrap\"> <a href=\"javascript:__doPostBack('LogonHistory1$dgResult$_ctl2$_ctl4','')\">在线时间 </a> </td> <td nowrap=\"nowrap\"> <a href=\"javascript:__doPostBack('LogonHistory1$dgResult$_ctl2$_ctl5','')\">国内流量 </a> </td> <td nowrap=\nowrap\"> <a href=\"javascript:__doPostBack('LogonHistory1$dgResult$_ctl2$_ctl6','')\">国际流量 </a> </td> </tr> <tr nowrap=\"nowrap\" align=\"Center\" style=\"background-color:White;height:25px;\"> <td>10.18.2.10 </td> <td nowrap=\"nowrap\" align=\"Left\">2010-1-27 9:15:32 </td> <td nowrap=\"nowrap";
                int count = Html.Length;
                int starIndex = Html.IndexOf("<td>", 0, count);
                int endIndex = Html.IndexOf("</td>", starIndex, count - starIndex);
                string IP = Html.Substring(starIndex+4, endIndex - starIndex-4);
      

  6.   


    呃……
    我上面那部分网页源文件是那个页面的全部源文件的一部分,
    那个源文件是要通过程序自动读出来的,
    然后让程序返回那个IP,
    那么,我应该用什么webbrowser的语句把<td> 和 之后的第一个 </td>之间的东西取出来?
    webBrowser.Document.All("");应该是读取整个网页文档吧?
      

  7.   

    读取整个网页文档用正则也可以的
     string Html = "<FONT face=\"宋体\"> <table cellspacing=\"0\" rules=\"all\" border=\"1\" id=\"LogonHistory1_dgResult\" style=\"border-width:1px;border-style:solid;font-size:X-Small;width:100%;border-collapse:collapse;\"> <tr class=\"tableTag\" nowrap=\nowrap\" align=\"Center\"> <td nowrap=\"nowrap\"> <a href=\"javascript:__doPostBack('LogonHistory1$dgResult$_ctl2$_ctl0','')\">登录IP </a> </td> <td nowrap=\"nowrap\"> <a href=\"javascript:__doPostBack('LogonHistory1$dgResult$_ctl2$_ctl1','')\">登录时间 </a> </td> <td nowrap=\"nowrap\"> <a href=\"javascript:__doPostBack('LogonHistory1$dgResult$_ctl2$_ctl2','')\">登出时间 </a> </td> <td nowrap=\"nowrap\"> <a href=\"javascript:__doPostBack('LogonHistory1$dgResult$_ctl2$_ctl4','')\">在线时间 </a> </td> <td nowrap=\"nowrap\"> <a href=\"javascript:__doPostBack('LogonHistory1$dgResult$_ctl2$_ctl5','')\">国内流量 </a> </td> <td nowrap=\nowrap\"> <a href=\"javascript:__doPostBack('LogonHistory1$dgResult$_ctl2$_ctl6','')\">国际流量 </a> </td> </tr> <tr nowrap=\"nowrap\" align=\"Center\" style=\"background-color:White;height:25px;\"> <td>10.18.2.10 </td> <td nowrap=\"nowrap\" align=\"Left\">2010-1-27 9:15:32 </td> <td nowrap=\"nowrap";
               Regex r = new Regex(@"(?is)(?<=<td>)(?:(?!</?/td\b).)*(?=</td>)", RegexOptions.Compiled | RegexOptions.IgnoreCase);
                foreach (Match m in r.Matches(Html))
                {        
                    foreach(Capture c in m.Captures)
                    {            
                        string IP = c.Value;
                }
                }
      

  8.   

    弹出一个“安全信息”对话框
    -------
    弹出的对话框在webBrowser中 还是类似win.open() 
    能不能不要弹出?
      

  9.   


    访问那个网站的时候,先会弹出“安全证书”对话框,点击“是”后会接着弹出一个“安全信息”对话框,再点击“是”后才能访问到登陆界面。
    应该是在webbrowser弹出的。(==!汗,我不知道什么是win.open())
    不知道能否不要弹出,因为即使在浏览器打开那个网站也会弹出安全证书。
      

  10.   

    IE -- 工具--internet选项--安全--自定义级别----其他---加载应用程序 和不安全文件 --选 启动试试
      

  11.   

    这个问题比较复杂
    核心:可以利用win32 API函数实现,导入User32.dll。
    思路:启动timer,获取窗体,操作鼠标模拟点击事件,关闭timer
    参考代码: [DllImport("user32.dll", SetLastError = true)]
    static extern IntPtr FindWindow(string lpClassName, string lpWindowName);
    [DllImport("User32.dll ")]
    public static extern System.IntPtr FindWindowEx(System.IntPtr parent, System.IntPtr childe, string strclass, string strname);
    [DllImport("user32.dll", EntryPoint = "SendMessage", SetLastError = true, CharSet = CharSet.Auto)]
    private static extern int SendMessage(IntPtr hwnd, uint wMsg, int wParam, int lParam);
    [DllImport("user32.dll", EntryPoint = "SetForegroundWindow", SetLastError = true)]
    private static extern void SetForegroundWindow(IntPtr hwnd);
    const uint BM_CLICK = 0xF5; //取得消息框的句柄
    IntPtr p = FindWindowEx(System.IntPtr.Zero, System.IntPtr.Zero, null, "Choose a digital certificate"); //取得OK按钮的句柄
    IntPtr hwndok = FindWindowEx(p, System.IntPtr.Zero, null, "Ok"); //显示到前端
    SetForegroundWindow(p); //模拟点击按钮
    SendMessage(hwndok, BM_CLICK, 0, 0); this.Close();