實驗室要每天簽到,所以用webBrowser寫了一個一鍵簽到的小程序,期間遇到些很有價值的問題,最大的收穫就是對navigated事件 和 DocumentCompleted事件的瞭解。
private void webBrowser1_DocumentCompleted(object sender, WebBrowserDocumentCompletedEventArgs e)
{
if (webBrowser1.ReadyState < WebBrowserReadyState.Complete) return;
if (flag == true)
{
//HtmlElementCollection 是一個集合類型,Submit中保存了表單中所有元素
HtmlElementCollection Submit = webBrowser1.Document.All;
HtmlElement tbUserid = webBrowser1.Document.All["username"];
HtmlElement tbPasswd = webBrowser1.Document.All["password"];
if (tbUserid == null || tbPasswd == null)
return;
tbUserid.SetAttribute("value", "Dp");
tbPasswd.SetAttribute("value", "123456");
getSubmit(Submit);
}
else
{
HtmlElement signIn = webBrowser1.Document.GetElementById("signin");
if (signIn == null)
return;
signIn.InvokeMember("click");
}
}
//按元素類型獲取,invokeMember方法模擬點擊,GetAttribut方法檢索已命名屬性的值
private void getSubmit(HtmlElementCollection Submit)
{
foreach (HtmlElement e in Submit)
{
string str = e.GetAttribute("type");
if (str == "submit")
{
e.InvokeMember("click");
}
}
}
首先是Documentscompleted事件的代碼,其中flag用來指定一級或二級頁面,因爲只有兩個,bool型完全足夠了,flag爲true時檢索登錄頁面,獲取登錄id、密碼,登錄button等元素,並自動填充表單。
對於表單元素中有id屬性的,可以用document.All["value"] 或 document.GetElementById("value") 獲取相應元素,要注意的是用這兩種方法必須對檢索結果是否爲空進行判斷,不然會報錯。
而沒有id屬性的只用靠遍歷所有元素獲得,這裏用的是“type”類型,一定要注意,選取檢索的類型命名一定要是唯一的,不然會返回所有匹配項。
獲得元素後,用SetAttribute()方法填寫表單,用InvokeMember()方法模擬點擊,實現自動填寫表單並提交的功能。
private void webBrowser1_Navigated(object sender, WebBrowserNavigatedEventArgs e)
{
//label1.Text = webBrowser1.Document.Url.ToString();
flag = !flag;
}
接下來是Navigated事件,雖然很簡單,卻是關鍵所在,因爲如果不對navigate事件進行處理,webBrowser.url會一直是一級頁面,這樣也就不能獲取到跳轉後頁面的元素。
MSDN上對navigate的定義:處理 Navigated 事件,在 WebBrowser 控件導航到新文檔時接收通知。如果 Navigated 事件發生,則新文檔已開始加載,這意味着可以通過 Document、DocumentText 和DocumentStream 屬性訪問所加載的文檔。處理 DocumentCompleted 事件,在 WebBrowser 控件完成加載新文檔時接收通知。
整個流程就是Navigated --> DocumentCompleted --> Navigated --> DocumentCompleted,也就是每次跳轉後都會重新調用DocumentCompleted事件對網頁進行處理,所以所有操作都該放在DocumentCompleted中,放在Navigated中的話不能獲取所有元素,只是body之前的。