首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> 更多程式語言 >> 更多程式設計知識

C# WebBrowser 擷取驗證碼圖片:DOM 定位、絕對定位、DrawToBitmap 完整實作

     編輯:更多程式設計知識

核心挑戰

  • 驗證碼圖片 URL 每次請求皆不同,直接 `WebClient.Download` 會取得新圖片而非當前顯示。
  • `WebBrowser` 控制項已載入完整頁面,**直接截取畫面區域**最可靠。
  • `DrawToBitmap` 在控制項**未顯示於視窗**時才能正常繪製;加入表單會導致全白。

實作步驟

1. 定位驗證碼 `` 元素


HtmlElement captchaImg = null;
foreach (HtmlElement img in webBrowser.Document.Images) {
    string src = img.GetAttribute("src").ToLower();
    if (src.EndsWith("randomimage.aspx") || src.Contains("captcha")) {
        captchaImg = img;
        break;
    }
}
if (captchaImg == null) throw new Exception("找不到驗證碼圖片");

2. 將元素移至頁面左上角 (避免捲軸/遮擋)


captchaImg.Style = "position: absolute; z-index: 9999; top: 0; left: 0;";

3. 建立隱藏 WebBrowser 並截圖


using (var wb = new WebBrowser()) {
    wb.ScriptErrorsSuppressed = true;
    wb.Navigate("https://target-site.com/login");
    while (wb.ReadyState != WebBrowserReadyState.Complete)
        Application.DoEvents(); // 簡易等待,實務建議用 DocumentCompleted 事件

    // 定位元素 (同上)
    HtmlElement img = ...;
    img.Style = "position: absolute; z-index: 9999; top: 0; left: 0;";

    // 截圖:尺寸取自 ClientRectangle
    Rectangle rect = img.ClientRectangle;
    using (var bmp = new Bitmap(rect.Width, rect.Height)) {
        wb.DrawToBitmap(bmp, new Rectangle(Point.Empty, rect.Size));
        pictureBox1.Image = bmp; // 顯示於 UI
        // 或 bmp.Save("captcha.png", ImageFormat.Png);
    }
}

關鍵細節:DrawToBitmap 全白問題

現象原因解決
截圖全白`WebBrowser` 已加入表單控制項集合 (可見)**不要** `Controls.Add(wb)`,保持獨立實例
截圖為空/黑頁面尚未完成渲染監聽 `DocumentCompleted` 事件,並確認 `ReadyState == Complete`
尺寸為 0元素 `ClientRectangle` 尚未計算強制 `webBrowser.PerformLayout()` 或稍作延遲

完整 WinForms 範例


public partial class CaptchaCaptureForm : Form {
    PictureBox pic = new PictureBox { Dock = DockStyle.Fill, SizeMode = PictureBoxSizeMode.Zoom };
    Button btn = new Button { Text = "擷取驗證碼", Dock = DockStyle.Bottom, Height = 40 };

    public CaptchaCaptureForm() {
        Controls.Add(pic); Controls.Add(btn);
        btn.Click += async (s, e) => await CaptureCaptchaAsync();
    }

    async Task CaptureCaptchaAsync() {
        btn.Enabled = false;
        try {
            using (var wb = new WebBrowser()) {
                wb.ScriptErrorsSuppressed = true;
                var tcs = new TaskCompletionSource();
                wb.DocumentCompleted += (s, e) => tcs.TrySetResult(true);
                wb.Navigate("https://example.com/login");
                await tcs.Task; // 等待載入完成

                HtmlElement img = wb.Document.Images.Cast()
                    .FirstOrDefault(el => el.GetAttribute("src").EndsWith("captcha.jpg"));
                if (img == null) throw new Exception("未找到驗證碼");

                img.Style = "position: absolute; z-index: 9999; top: 0; left: 0;";
                await Task.Delay(200); // 等待重繪

                Rectangle rect = img.ClientRectangle;
                using (var bmp = new Bitmap(rect.Width, rect.Height)) {
                    wb.DrawToBitmap(bmp, new Rectangle(Point.Empty, rect.Size));
                    pic.Image?.Dispose();
                    pic.Image = (Bitmap)bmp.Clone();
                }
            }
        } catch (Exception ex) {
            MessageBox.Show(ex.Message);
        } finally {
            btn.Enabled = true;
        }
    }
}

現代替代方案:Selenium / Playwright / Puppeteer Sharp

  • `WebBrowser` 底層為 IE/Edge WebView1,**已停止更新**,不支援現代 JS/CSS。
  • 新專案建議使用 **Selenium WebDriver** (Headless Chrome/Firefox) 或 **Playwright Sharp**:
    
    // Playwright Sharp 範例
    using var playwright = await Playwright.CreateAsync();
    using var browser = await playwright.Chromium.LaunchAsync(new() { Headless = true });
    var page = await browser.NewPageAsync();
    await page.GotoAsync("https://example.com/login");
    var img = await page.QuerySelectorAsync("img.captcha");
    await img.ScreenshotAsync(new() { Path = "captcha.png" });
    

結語

`WebBrowser.DrawToBitmap` 搭配 DOM 絕對定位,能可靠擷取當前頁面顯示的驗證碼圖片,核心訣竅在於**不將控制項加入表單**。但 `WebBrowser` 技術已過時,新專案請改用 Headless Chromium 生態工具,獲得更佳相容性與維護性。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved