引言
最近和一位朋友探討獲取WebBrowser訪問的網頁中驗證圖片的方法,起先想到的就是通過WebClient直接去下載當前頁面中引用的驗證碼圖片,但繼而想到這會涉及一些問題:一是驗證碼可能會在每次請求時都發生變化,二是將WebClient與WebBrowser的Cookies甚至Session關聯起來是件很難的事。
而後就想到了可以放棄WebBrowser,始終使用WebRequest進行較為底層的訪問,以避免多次獲取驗證碼產生變化導致不一致的情況,不過這種辦法操作起來還是比較復雜的。
然後又想到這種變通的方法——抓圖。只需要直接通過WebBrowser截圖,並將驗證碼以外的部分裁剪掉,就可以了。
思路
首先要分析一下那位朋友要獲取的驗證圖片元素特征:
網址:http://www.jcard.cn/Charge/UCardDirectCharge.aspx?category=AAWYVVWYKV&product=AAWYVVWYKV010CV
這裡很簡單,我們只要找到src屬性為“RandomImage.aspx”結尾的圖片,就找到我們所需的這個元素了。
找到這個元素之後,為了方便確定其位置,並確保其不會超出WebBrowser可視范圍,我們要為它賦予一個內聯樣式,使之處於頁面的絕對左上角,並設置z-index為9999,以避免被其他元素覆蓋,這個樣式即為:
"position: absolute; z-index: 9999; top: 0px; left: 0px"
這之後就可以通過WebBrowser的DrawToBitmap方法截圖了,截圖的寬和高可通過上述元素的ClientRectangle屬性取得。
實現
那麼現在建立一個WinForm項目來做測試,設計如下界面:
然後為按鈕編寫事件處理函數:
privatevoid button1_Click(object sender, EventArgs e)
{
var wb =newWebBrowser();
wb.Navigate("http://www.jcard.cn/Charge/UCardDirectCharge.aspx?category=AAWYVVWYKV&product=AAWYVVWYKV010CV");
//等待加載完畢
while (wb.ReadyState
//遍歷尋找驗證圖像所在元素
foreach (HtmlElement f in wb.Document.Images)
{
if (f.GetAttribute("src").ToLower().EndsWith("randomimage.aspx"))
{
//將元素絕對定位到頁面左上角
f.Style ="position: absolute; z-index: 9999; top: 0px; left: 0px";
//抓圖
var b =newBitmap(f.ClientRectangle.Width, f.ClientRectangle.Height);
wb.DrawToBitmap(b, newRectangle(newPoint(), f.ClientRectangle.Size));
pictureBox1.Image = b;
break;
}
}
}
編譯並運行以測試:
點擊按鈕,稍等片刻,即可在PictureBox中顯示出完整的驗證碼圖片了。
提示
WebBrowser的DrawToBitmap方法是隱藏的,不受智能感知提示支持,我不知道為什麼會這樣,但我知道DrawToBitmap方法確實存在問題,就是截圖出來全白現象,據我觀察,發生這種現象和是否顯示WebBrowser控件有關,只要在窗體上顯示了WebBrowser控件,截圖出來就是全白,而如果不將WebBrowser加載到窗體,截圖就是正常的,具體原因不明,只能再次感歎WebBrowser這個強大的控件編寫的也太粗濫了。