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("找不到驗證碼圖片");
captchaImg.Style = "position: absolute; z-index: 9999; top: 0; left: 0;";
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);
}
}
| 現象 | 原因 | 解決 |
|---|---|---|
| 截圖全白 | `WebBrowser` 已加入表單控制項集合 (可見) | **不要** `Controls.Add(wb)`,保持獨立實例 |
| 截圖為空/黑 | 頁面尚未完成渲染 | 監聽 `DocumentCompleted` 事件,並確認 `ReadyState == Complete` |
| 尺寸為 0 | 元素 `ClientRectangle` 尚未計算 | 強制 `webBrowser.PerformLayout()` 或稍作延遲 |
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;
}
}
}
// 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 生態工具,獲得更佳相容性與維護性。