之前写过一篇“C# WebBrowser类使用总结”,前段时间因密码泄漏事件淘宝登录启用了验证码功能,导致之前所写的淘宝店铺助手使用的WebClient没有用武之地,当然还可以考虑弄个验证码自动识别或弹出给用户输入的做法,但没玩过这方面的编程还是无从下手。
没办法只好改用回WebBrowser控件,实际使用中碰到3个问题:
1. URL重复提交不被处理的问题。
2. session超时后需要重新登录,但上回登录成功的cookie还生效,实际上并没有登录操作就被判断为已经登录。
3. 页面弹出窗体自动无法自动确认导致后续页面无法执行的问题。
现在已经都解决了,现把各个解决的解决记录一下。
1. URL重复提交不处理的问题。
我们采用在调用Navigate前给URL增加一个每次调用都不一样的参数,就可以让控件以为是不同的URL所以会去处理。
[csharp]
if (url.IndexOf(‘?’) == -1)
{
url += “?”;
}
else
{
url += “&”;
}
_savedTick = DateTime.Now.Ticks / 100000; // 10-ms
url += “rtick=” + _savedTick.ToString();
_browser.Stop();
_browser.Navigate(url, target, bytePost, header);
[/csharp]
另外发现有了个rtick参数后我们就可以的DocumentCompleted事件中判断URL里有没有这个参数,有才认为是对应URL的反回结果,所以上面把rtick值保存到类变量_savedTick中了,使用如下:
[csharp]
if (response != null && e.Url.ToString().Contains(string.Format(“rtick={0}”, _savedTick)))
{
_response = response;
_status = BrowserStatus.Ingnore;
_event.Set();
}
[/csharp]
2. 重新登录时修改cookie
在网上找到使用wininet.dll的InternetSetCookie函数可以修改cookie:
[csharp]
[DllImport(“wininet.dll”, CharSet = CharSet.Auto, SetLastError = true)]
public static extern bool InternetSetCookie(string lpszUrlName, string lbszCookieName, string lpszCookieData);
// 登录时如果判断Document有效就把用于判断是否已登录的cookie关键字修改成一个固定字符串值
if (_browser.Document != null)
{
// set cookie
InternetSetCookie(loginUrl, “_nk_”, IGNORE_USER);
}
[/csharp]
然后在检查是否已经登录成功时忽略掉提交前修改成的用户名:
[csharp]
bool isLogin = false;
Regex rx = new Regex(“_nk_=(.*?);”, RegexOptions.IgnoreCase);
Match check = rx.Match(cookie);
string username = null;
if (check.Groups.Count == 2)
{
username = check.Groups[1].Value;
}
if (username == IGNORE_USER)
{
// 忽略用户
return isLogin;
}
[/csharp]
3. 禁用页面的javascript弹出窗体
引用名为Microsoft.mshtml的COM组件,描述名是Microsoft HTML Object Library,对应的tlb文件是mshtml.tlb。
然后using mshtml;
处理WebBrowser的Navigated事件:
[csharp]
using mshtml;
_browser.Navigated += new WebBrowserNavigatedEventHandler(_browser_Navigated);
private void _browser_Navigated(object sender, WebBrowserNavigatedEventArgs e)
{
IHTMLDocument2 vDocument = (IHTMLDocument2)_browser.Document.DomDocument;
// 自动确认弹出窗体
vDocument.parentWindow.execScript(“function alert(){return;}”, “javascript”);
vDocument.parentWindow.execScript(“function confirm(){return;}”, “javascript”);
vDocument.parentWindow.execScript(“function showModalDialog(){return;}”, “javascript”);
}
[/csharp]
Tags: C#/.NET