7,655
社区成员
发帖
与我相关
我的任务
分享
/// <summary>
/// 模拟自动登录的网页客户端
/// </summary>
private showjim.sys.net.webClient _loginWebClient;
/// <summary>
/// 模拟自动登录的网页客户端
/// </summary>
private showjim.sys.net.webClient loginWebClient
{
get
{
if (_loginWebClient == null)
{
_loginWebClient = new showjim.sys.net.webClient(null);
_loginWebClient.Credentials = new CredentialCache();
}
return _loginWebClient;
}
}
/// <summary>
/// 模拟自动登录的网页客户端是否已进行过登录操作
/// </summary>
private bool isLogin = false;
/// <summary>
/// 模拟自动登录后抓取页面信息
/// </summary>
/// <param name="url">抓取页面地址</param>
/// <returns>页面数据</returns>
public byte[] downData(string url, string loginUrl, bool reLogin)
{
byte[] data = null;
afterLoginCookie = System.IO.File.ReadAllText(@"C:\Documents and Settings\Administrator\桌面\logindata\login_c_" + (new Uri(loginUrl)).ToString().GetHashCode().ToString() + ".data");
if (reLogin)
{
isLoginData = true;
postData_ = showjim.sys._object.deSerialize<loginData[]>(System.IO.File.ReadAllBytes(@"C:\Documents and Settings\Administrator\桌面\logindata\login_" + (new Uri(loginUrl)).ToString().GetHashCode().ToString() + ".data"), null).toList<loginData[], loginData, loginData>(v => v);
if (url != null && url.Length != 0 && login())
{
//loginWebClient.Headers.Add("Cookie", loginWebClient.ResponseHeaders["Set-Cookie"]);
loginWebClient.mergeDomainCookie(new Uri(url), loginWebClient.ResponseHeaders["Set-Cookie"], afterLoginCookie);
data = _downData(url, loginUrl);
}
}
else
{
ServicePointManager.Expect100Continue = false;
showjim.sys.net.webClient loginWebClient = new showjim.sys.net.webClient();
loginWebClient.Credentials = new CredentialCache();
loginWebClient.mergeDomainCookie(new Uri(url), (string)null, afterLoginCookie);
data = _downData(url, loginUrl);
loginWebClient.Dispose();
}
return data;
}
#region 模拟自动登录后抓取页面信息
/// <summary>
/// 模拟自动登录后抓取页面信息
/// </summary>
/// <param name="url">抓取页面地址</param>
/// <returns>页面数据</returns>
public byte[] downData(string url)
{
byte[] data = null;
if (url != null && url.Length != 0 && (isLogin || login()))
{
loginWebClient.Headers.Add("Cookie", loginWebClient.ResponseHeaders["Set-Cookie"]);
data = _downData(url, url);
}
return data;
}
/// <summary>
/// 模拟自动登录后抓取页面信息
/// </summary>
/// <param name="url">抓取页面地址</param>
/// <param name="referer">来源泉页面地址</param>
/// <param name="cookies">登录后的cookie信息</param>
/// <param name="documentCookie">登录后的cookie信息</param>
/// <param name="httpOnlyCookie">登录后的httpOnly相关cookie信息</param>
/// <returns>页面数据</returns>
public byte[] downData(string url, string referer, List<Cookie> cookies, string documentCookie, string httpOnlyCookie)
{
byte[] data = null;
if (url != null && url.Length != 0)
{
if (referer != null && referer.Length != 0) _downData(referer, null);
loginWebClient.mergeDomainCookie(new Uri(url), cookies, documentCookie, httpOnlyCookie);
data = _downData(url, referer);
}
return data;
}
/// <summary>
/// 模拟自动登录后抓取页面信息
/// </summary>
/// <param name="url">抓取页面地址</param>
/// <param name="referer">来源泉页面地址</param>
/// <returns>页面数据</returns>
private byte[] _downData(string url, string referer)
{
byte[] data = null;
loginWebClient.Headers.Add(showjim.sys.net.webClient.UserAgentName, showjim.sys.net.webClient.defaultUserAgent);
if (referer != null && referer.Length != 0) loginWebClient.Headers.Add(showjim.sys.net.webClient.RefererName, referer);
try { data = loginWebClient.DownloadData(url); }
catch (Exception error)
{
showjim.sys.exception.debug.writeDebug(MethodBase.GetCurrentMethod(), "页面 " + url + " 下载失败", error);
}
return data;
}
#endregion
#region 示例用法
/// <summary>
/// 示例用法
/// </summary>
private static void example()
{
#region 从WebBrowser中截取登录POST信息
System.Windows.Forms.WebBrowser webBrowser = new System.Windows.Forms.WebBrowser();
example_webAutoLogin = new showjim.sys.net.webAutoLogin(webBrowser, example_login, true);
example_webAutoLogin.ready("http://www.showjim.com/user/login.htm");
#endregion
}
/// <summary>
/// 示例:网页自动登录对象
/// </summary>
private static showjim.sys.net.webAutoLogin example_webAutoLogin;
/// <summary>
/// 示例:截取登录POST信息后的处理函数
/// </summary>
private static void example_login()
{
string html = System.Text.Encoding.Default.GetString(example_webAutoLogin.downData("http://www.showjim.com/user/myPage.htm"));
}
#endregion
}
终于发完了,因为缺少一些过时的类库支持,这些代码是不能通过编译的。
当时因为需要支持除了含有验证码的主流网站的模拟登录,所有有很多补丁代码,细节问题太多,不是简单能说清楚的,所以只好发这几个核心代码。
楼上那位同学将就着看。 #region 截取登录POST信息处理函数
/// <summary>
/// 截取登录POST信息处理函数
/// </summary>
/// <param name="eventProvider">截取POST信息相关事件</param>
/// <param name="postUrl">登录POST目标页面地址</param>
/// <param name="flags"></param>
/// <param name="targetFrameName"></param>
/// <param name="postData">登录时的POST数据</param>
/// <param name="headers">登录时的Header数据</param>
/// <param name="canCancel"></param>
private void savePost(object eventProvider, ref object postUrl, ref object flags, ref object targetFrameName, ref object postData, ref object headers, ref bool canCancel)
{
if (!isLoginData)
{
string url = postUrl as string;
if (url != null && (url.StartsWith("http://", StringComparison.CurrentCultureIgnoreCase) || url.StartsWith("https://", StringComparison.CurrentCultureIgnoreCase)))
{
savePost(null, url, postData as byte[], headers as string);
if (isMouseAndKey)
{
isMouseAndKey = false;
if (beforeNavigate2 != null) beforeNavigate2();
if (!isSaveResponseCookie)
{
isSaveResponseCookie = true;
setSaveResponseCookieTime(null, null);
}
}
}
}
}
/// <summary>
/// 截取登录POST信息处理函数
/// </summary>
/// <param name="loginUrl">登录页面地址</param>
/// <param name="postUrl">登录POST目标页面地址</param>
/// <param name="postData">登录时的POST数据</param>
/// <param name="headers">POST相关HTTP头信息</param>
private void savePost(string loginUrl, string postUrl, byte[] postData, string headers)
{
if (postData_ != null && isReady)
{
if (postData_.Count == 0 && (loginUrl != null && loginUrl.Length != 0))
{
postData_.Add(new loginData
{
loginUrl = webBrowser.Url.ToString(),
postUrl = null,
cookie = webBrowser.Document.Cookie,
data = null,
contentType = null,
});
}
string contentType = null, contentTypeString = "Content-Type:";
if (headers != null && headers.Length != 0 && headers.StartsWith(contentTypeString)) contentType = headers.Substring(contentTypeString.Length);
loginData newLoginData = new loginData
{
loginUrl = loginUrl == null || loginUrl.Length == 0 ? webBrowser.Url.ToString() : loginUrl,
postUrl = postUrl as string,
cookie = webBrowser.Document.Cookie,
data = postData as byte[],
contentType = contentType,
};
if (newLoginData.data == null) newLoginData.data = new byte[0];
else if (newLoginData.data.Length > 0 && newLoginData.data[newLoginData.data.Length - 1] == 0)
{
byte[] newData = new byte[newLoginData.data.Length - 1];
if (newLoginData.data.Length > 1) Buffer.BlockCopy(newLoginData.data, 0, newData, 0, newLoginData.data.Length - 1);
newLoginData.data = newData;
}
postData_.Add(newLoginData);
}
}
#endregion
#region 保存登录后的cookie信息
/// <summary>
/// 保存登录后的cookie信息时间
/// </summary>
private void setSaveResponseCookieTime(object sender, WebBrowserNavigatingEventArgs e)
{
if (isSaveResponseCookie)
{
saveResponseCookieTime = DateTime.MinValue;
webBrowser.DocumentCompleted += saveResponseCookie;
}
}
/// <summary>
/// 保存登录后的cookie信息
/// </summary>
private void saveResponseCookie(object sender, WebBrowserDocumentCompletedEventArgs e)
{
webBrowser.DocumentCompleted -= saveResponseCookie;
afterLoginCookie = webBrowser.Document.Cookie;
showjim.sys.threading.task.add(saveResponseCookie, saveResponseCookieTime = DateTime.Now.AddSeconds(1), new DateTime(saveResponseCookieTime.Ticks), null);
}
/// <summary>
/// 保存登录后的cookie信息
/// </summary>
/// <param name="time">保存登录后的cookie信息时间确认</param>
private void saveResponseCookie(DateTime time)
{
if (isSaveResponseCookie && time == saveResponseCookieTime)
{
isSaveResponseCookie = false;
isLoginData = true;
if (isCancelRead) cancel();
saveResponseCookie();
}
}
/// <summary>
/// 保存登录后的cookie信息
/// </summary>
private void saveResponseCookie()
{
//System.IO.File.WriteAllBytes(@"C:\Documents and Settings\Administrator\桌面\logindata\login_" + readyUrl.GetHashCode().ToString() + ".data", postData.serialize());
//System.IO.File.WriteAllText(@"C:\Documents and Settings\Administrator\桌面\logindata\login_c_" + readyUrl.GetHashCode().ToString() + ".data", afterLoginCookie);
if (afterResponseCookie != null) afterResponseCookie();
}
#endregion
#region 中断截取登录POST信息
/// <summary>
/// 中断截取登录POST信息
/// </summary>
public void cancel()
{
if (isReady)
{
SHDocVw.WebBrowser browserActiveX = webBrowser.ActiveXInstance as SHDocVw.WebBrowser;
browserActiveX.BeforeNavigate2 -= savePostHandler;
isReady = false;
}
}
#endregion
#region 模拟自动登录
/// <summary>
/// 模拟自动登录
/// </summary>
/// <returns>自动登录页面数据是否成功下载,不代表登录是否成功</returns>
private bool login()
{
isLogin = false;
if (isLoginData)
{
ServicePointManager.Expect100Continue = false;
try
{
byte[] data = null;
int locationCount;
string location;
Uri uri = new Uri(postData_[0].loginUrl);
loginWebClient.AllowAutoRedirect = false;
loginWebClient.Headers.Add(showjim.sys.net.webClient.UserAgentName, showjim.sys.net.webClient.defaultUserAgent);
loginWebClient.Headers.Add(showjim.sys.net.webClient.ContentTypeName, showjim.sys.net.webClient.defaultPostContentType);
loginWebClient.Headers.Add("Cookie", postData_[0].cookie);
loginWebClient.DownloadData(uri);
foreach (loginData postData in postData_)
{
if (postData.postUrl != null)
{
loginWebClient.Headers.Add(showjim.sys.net.webClient.UserAgentName, showjim.sys.net.webClient.defaultUserAgent);
loginWebClient.Headers.Add(showjim.sys.net.webClient.ContentTypeName, postData.contentType == null ? showjim.sys.net.webClient.defaultPostContentType : postData.contentType);
loginWebClient.Headers.Add(showjim.sys.net.webClient.RefererName, postData.loginUrl);
uri = new Uri(postData.postUrl);
loginWebClient.mergeDomainCookie(uri, loginWebClient.ResponseHeaders["Set-Cookie"], postData.cookie);
data = loginWebClient.UploadData(uri, showjim.sys.web.http.code.methodType.POST.ToString(), postData.data);
for (locationCount = 3, location = loginWebClient.httpRequest.GetResponse().Headers["Location"]; locationCount != 0 && location != null && location.Length != 0; locationCount--)
{
loginWebClient.Headers.Add(showjim.sys.net.webClient.UserAgentName, showjim.sys.net.webClient.defaultUserAgent);
loginWebClient.Headers.Add(showjim.sys.net.webClient.ContentTypeName, showjim.sys.net.webClient.defaultPostContentType);
loginWebClient.Headers.Add(showjim.sys.net.webClient.RefererName, postData.loginUrl);
loginWebClient.mergeDomainCookie(uri, loginWebClient.ResponseHeaders["Set-Cookie"], postData.cookie);
data = loginWebClient.DownloadData(location);
location = loginWebClient.httpRequest.GetResponse().Headers["Location"];
}
}
}
loginWebClient.mergeDomainCookie(new Uri(postData_[0].loginUrl), loginWebClient.ResponseHeaders["Set-Cookie"], afterLoginCookie);
isLogin = true;
System.Diagnostics.Trace.Write(data == null ? -1 : data.Length);
}
catch (Exception error)
{
showjim.sys.exception.debug.writeDebug(MethodBase.GetCurrentMethod(), "模拟登录页面下载失败", error);
}
finally { loginWebClient.AllowAutoRedirect = true; }
}
return isLogin;
}
#endregion
未完待续 #region 准备截取登录POST信息
/// <summary>
/// 准备截取登录POST信息
/// </summary>
/// <param name="isAgain">是否再次准备</param>
/// <returns>是否准备好截取登录POST信息</returns>
private bool ready(bool isAgain)
{
if (webBrowser != null && (!isReady))
{
SHDocVw.WebBrowser browserActiveX = webBrowser.ActiveXInstance as SHDocVw.WebBrowser;
if (isReady = browserActiveX != null)
{
isLoginData = false;
readData(isAgain);
if (!isAgain) afterLoginCookie = null;
browserActiveX.BeforeNavigate2 += savePostHandler;
}
}
return isReady;
}
/// <summary>
/// 准备截取登录POST信息
/// </summary>
/// <param name="loginUrl">登录页面地址</param>
public void ready(string loginUrl)
{
if (webBrowser != null)
{
bool isReadyLogin = false;
Uri readyUri = null;
try
{
readyUrl = (readyUri = new Uri(loginUrl)).ToString();
if (webBrowser.Url != null && webBrowser.Url.ToString() == readyUrl) webBrowser.Navigate(showjim.sys.net.webClient.blankUrl);
webBrowser.DocumentCompleted += readyLogin;
webBrowser.Navigated += navigated;
isReadyLogin = true;
webBrowser.Hide();
//onReady(readyUri);
webBrowser.Url = readyUri;
}
catch (Exception error)
{
if (isReadyLogin)
{
webBrowser.DocumentCompleted -= readyLogin;
webBrowser.Navigated -= navigated;
}
showjim.sys.exception.debug.throwException(MethodBase.GetCurrentMethod(), "登录页面地址错误: " + (loginUrl == null ? String.Empty : loginUrl), error);
}
}
}
/// <summary>
/// 导航结束之后重置登录页面地址
/// </summary>
private void navigated(object sender, WebBrowserNavigatedEventArgs e)
{
webBrowser.Navigated -= navigated;
readyUrl = webBrowser.Url.ToString();
}
/// <summary>
/// 再次准备截取登录POST信息
/// </summary>
public void readAgain()
{
if (webBrowser != null && (!isReady) && isLoginData) readyLogin(null, null);
}
/// <summary>
/// 准备截取登录POST数据
/// </summary>
/// <param name="isAgain">是否再次准备</param>
private void readData(bool isAgain)
{
if (isAgain)
{
if (postData_ == null) postData_ = new List<loginData>();
}
else postData_ = new List<loginData>();
}
/// <summary>
/// 准备截取登录POST信息
/// </summary>
private void readyLogin(object sender, WebBrowserDocumentCompletedEventArgs e)
{
if (sender != null) webBrowser.DocumentCompleted -= readyLogin;
if (sender == null || webBrowser.Url.ToString() == readyUrl)
{
isReady = false;
webBrowser.Document.InvokeScript("eval", new string[] { @"window.sHoWjIm_AutoLogin=function(s)
{
for(var i=frames.length;--i>=0;) frames[i].eval(s);
eval(s);
};" });
Thread.Sleep(100);
webBrowser.Document.InvokeScript("sHoWjIm_AutoLogin", new string[] { @"Function.prototype.sHoWjIm_InheritActiveXObject=function()
{
var ThisFunction=this;
var ReturnFunction=function()
{
var FirstArgument=arguments.length?arguments[0]:null,Xmls=['microsoft.xmlhttp','msxml2.xmlhttp','msxml2.xmlhttp.3.0','msxml2.xmlhttp.4.0','msxml2.xmlhttp.5.0'],Index=Xmls.length-1;
if(FirstArgument) FirstArgument=FirstArgument.toString().toLowerCase();
while(Index>=0&&Xmls[Index]!=FirstArgument) Index--;
if(Index==-1)
{
var Arguments=[],FatherObject=null;
if(arguments.length)
{
Index=[];
for(var i=0;i<arguments.length;i++) { Index.push(i); Arguments.push(arguments[i]); }
eval('FatherObject=new sHoWjIm_AutoLogin.ActiveXObject(Arguments['+Index.join('],Arguments[')+']);');
ThisFunction.apply(FatherObject,Arguments);
return FatherObject;
}
else var FatherObject=new sHoWjIm_AutoLogin.ActiveXObject();
ThisFunction.apply(FatherObject,Arguments);
return FatherObject;
}
else return new sHoWjIm_AutoLogin(FirstArgument);
};
return ReturnFunction;
};
window.sHoWjIm_AutoLogin=function(Name)
{
this.Index=sHoWjIm_AutoLogin.Requests.length;
sHoWjIm_AutoLogin.Requests.push(this);
this.Request=new sHoWjIm_AutoLogin.ActiveXObject(Name);
eval('this._Onreadystatechange=function(){sHoWjIm_AutoLogin.Requests['+this.Index+'].Onreadystatechange();};');
this.Request.onreadystatechange=this._Onreadystatechange;
this.Onreadystatechange=function()
{
try { this.readyState=this.Request.readyState; } catch(e) {}
try { this.status=this.Request.status; } catch(e) {}
try { this.statusText=this.Request.statusText; } catch(e) {}
try { this.responseText=this.Request.responseText; } catch(e) {}
try { this.responseXML=this.Request.responseXML; } catch(e) {}
if(this.onreadystatechange) this.onreadystatechange();
}
this.eval=function(Name,Arguments)
{
var Value,Eval='Value=this.Request.'+Name+'(';
if(Arguments.length)
{
var Index=[];
for(var i=0;i<Arguments.length;i++) Index.push(i);
Eval+='Arguments['+Index.join('],Arguments[')+']';
}
eval(Eval+');');
return Value;
};
this.open=function()
{
this.OpenArguments=arguments;
return this.eval('open',arguments);
};
this.send=function()
{
var open=[],send=[];
for(var i=0;i<this.OpenArguments.length;i++) open.push(this.OpenArguments[i]);
for(var i=0;i<arguments.length;i++) send.push(arguments[i]);
try { window.external.saveAjaxPost(top==window||sHoWjIm_AutoLogin.iframeLocation?'':(sHoWjIm_AutoLogin.iframeLocation=document.location.toString()),open.join('\n'),send.join('\n')); }
catch(e){}
return this.eval('send',arguments);
};
this.abort=function() { return this.eval('abort',arguments); };
this.getAllResponseHeaders=function() { return this.eval('getAllResponseHeaders',arguments); };
this.getResponseHeader=function() { return this.eval('getResponseHeader',arguments); };
this.setRequestHeader=function() { return this.eval('setRequestHeader',arguments); };
};
sHoWjIm_AutoLogin.Requests=[];
sHoWjIm_AutoLogin.ActiveXObject=window.ActiveXObject;
sHoWjIm_AutoLogin.NewActiveXObject=function(){};
window.ActiveXObject=sHoWjIm_AutoLogin.NewActiveXObject.sHoWjIm_InheritActiveXObject();
XMLHttpRequest=null;
sHoWjIm_AutoLogin.createElement=document.createElement;
document.createElement=function(tag)
{
var element=sHoWjIm_AutoLogin.createElement(tag);
if(tag.toLowerCase()=='script')
{
element.attachEvent('onreadystatechange',function(){if(!event.srcElement.sHoWjIm_saveAjaxPost)window.external.saveAjaxPost(top==window||sHoWjIm_AutoLogin.iframeLocation?'':(sHoWjIm_AutoLogin.iframeLocation=document.location.toString()),'GET\n'+(event.srcElement.sHoWjIm_saveAjaxPost=event.srcElement.src),'');});
}
return element;
};" });
ready(sender == null);
}
webBrowser.Show();
}
#endregion
#region 截取Ajax登录POST信息处理函数
/// <summary>
/// 截取Ajax登录POST信息处理函数
/// </summary>
/// <param name="loginUrl">登录页面地址</param>
/// <param name="opens">open参数集合</param>
/// <param name="sends">send参数集合</param>
public void saveAjaxPost(string loginUrl, string opens, string sends)
{
if (opens != null)
{
string[] open = opens.Split('\n');
if (open.Length > 1)
{
string postUrl = open[1];
if (postUrl.Length != 0)
{
if (postUrl.IndexOf("://") == -1)
{
if (loginUrl.Length == 0) loginUrl = webBrowser.Document.Url.ToString();
string domain = loginUrl.getDomain();
if (postUrl.Length == 0) postUrl = domain;
else if (postUrl[0] == '/') postUrl = domain + postUrl.Substring(1);
else
{
int pathIndex = loginUrl.LastIndexOf('/');
if (pathIndex <= domain.Length) postUrl = domain + postUrl;
else postUrl = loginUrl.Substring(0, pathIndex) + postUrl;
}
}
Encoding encoding = Encoding.Default;
try { encoding = Encoding.GetEncoding(webBrowser.Document.Encoding); }
catch { }
savePost(loginUrl, postUrl, sends == null ? null : encoding.GetBytes(sends), null);
}
}
}
}
#endregion
未完待续 /// <summary>
/// 网页自动登录操作
/// </summary>
[System.Security.Permissions.PermissionSet(System.Security.Permissions.SecurityAction.Demand, Name = "FullTrust")]
[System.Runtime.InteropServices.ComVisibleAttribute(true)]
public class webAutoLogin
{
#region 网页自动登录数据
/// <summary>
/// 网页自动登录数据
/// </summary>
[Serializable]
public class loginData
{
/// <summary>
/// 登录页面地址
/// </summary>
public string loginUrl;
/// <summary>
/// 登录POST目标页面地址
/// </summary>
public string postUrl;
/// <summary>
/// 登录时的cookie信息
/// </summary>
public string cookie;
/// <summary>
/// 表单提交内容类型
/// </summary>
public string contentType;
/// <summary>
/// 登录时的POST数据
/// </summary>
public byte[] data;
/// <summary>
/// 登录后的cookie信息
/// </summary>
public string responseCookie;
}
#endregion
/// <summary>
/// 截取登录POST信息的网页浏览器
/// </summary>
private WebBrowser webBrowser;
/// <summary>
/// 截取登录POST信息处理函数
/// </summary>
private SHDocVw.DWebBrowserEvents2_BeforeNavigate2EventHandler savePostHandler;
/// <summary>
/// 是否已准备好截取登录POST信息
/// </summary>
private bool isReady = false;
/// <summary>
/// 准备登录页面地址
/// </summary>
private string readyUrl;
/// <summary>
/// 截取登录POST信息后是否中断截取行为
/// </summary>
private bool isCancelRead = false;
/// <summary>
/// 是否有键盘或鼠标操作
/// </summary>
private bool isMouseAndKey = false;
/// <summary>
/// 是否需要保存登录后的cookie信息
/// </summary>
private bool isSaveResponseCookie = false;
/// <summary>
/// 保存登录后的cookie信息时间
/// </summary>
private DateTime saveResponseCookieTime;
/// <summary>
/// 登录后的cookie信息
/// </summary>
private string afterLoginCookie;
/// <summary>
/// 是否已截取登录POST信息
/// </summary>
private bool isLoginData = false;
/// <summary>
/// 截取登录POST信息后的处理函数
/// </summary>
private showjim.sys.run beforeNavigate2;
/// <summary>
/// 截取登录后的cookie后的处理函数
/// </summary>
private showjim.sys.run afterResponseCookie;
/// <summary>
/// 网页自动登录数据
/// </summary>
private List<loginData> postData_;
/// <summary>
/// 网页自动登录数据
/// </summary>
public loginData[] postData
{
get
{
loginData[] newData = null;
if (postData_ != null)
{
int index = 0;
newData = new loginData[postData_.Count];
foreach (loginData oldData in postData_)
{
newData[index++] = new loginData
{
loginUrl = oldData.loginUrl,
postUrl = oldData.postUrl,
cookie = oldData.cookie,
data = oldData.data,
responseCookie = oldData.responseCookie,
contentType = oldData.contentType,
};
}
}
return newData;
}
}
/// <summary>
/// javascript调用C#处理<注册名称,处理委托>
/// </summary>
private Dictionary<string, run<string>> callBrowsers = new Dictionary<string, run<string>>();
#region 初始化网页自动登录实例
/// <summary>
/// 初始化网页自动登录实例
/// </summary>
/// <param name="webBrowser">截取登录POST信息的网页浏览器</param>
public webAutoLogin(WebBrowser webBrowser) : this(webBrowser, null, null, true) { }
/// <summary>
/// 初始化网页自动登录实例
/// </summary>
/// <param name="webBrowser">截取登录POST信息的网页浏览器</param>
/// <param name="beforeNavigate2">截取登录POST信息后的处理函数</param>
public webAutoLogin(WebBrowser webBrowser, showjim.sys.run beforeNavigate2) : this(webBrowser, beforeNavigate2, null, true) { }
/// <summary>
/// 初始化网页自动登录实例
/// </summary>
/// <param name="webBrowser">截取登录POST信息的网页浏览器</param>
/// <param name="beforeNavigate2">截取登录POST信息后的处理函数</param>
/// <param name="afterResponseCookie">截取登录后的cookie后的处理函数</param>
public webAutoLogin(WebBrowser webBrowser, showjim.sys.run beforeNavigate2, showjim.sys.run afterResponseCookie) : this(webBrowser, beforeNavigate2, afterResponseCookie, true) { }
/// <summary>
/// 初始化网页自动登录实例
/// </summary>
/// <param name="webBrowser">截取登录POST信息的网页浏览器</param>
/// <param name="beforeNavigate2">截取登录POST信息后的处理函数</param>
/// <param name="isCancelRead">截取登录POST信息后是否中断截取行为</param>
public webAutoLogin(WebBrowser webBrowser, showjim.sys.run beforeNavigate2, bool isCancelRead) : this(webBrowser, beforeNavigate2, null, isCancelRead) { }
/// <summary>
/// 初始化网页自动登录实例
/// </summary>
/// <param name="webBrowser">截取登录POST信息的网页浏览器</param>
/// <param name="beforeNavigate2">截取登录POST信息后的处理函数</param>
/// <param name="afterResponseCookie">截取登录后的cookie后的处理函数</param>
/// <param name="isCancelRead">截取登录POST信息后是否中断截取行为</param>
public webAutoLogin(WebBrowser webBrowser, showjim.sys.run beforeNavigate2, showjim.sys.run afterResponseCookie, bool isCancelRead)
{
if ((this.webBrowser = webBrowser) == null) showjim.sys.exception.debug.throwException(MethodBase.GetCurrentMethod(), "初始化失败,网页浏览器不能为空");
else
{
webBrowser.ObjectForScripting = this;
savePostHandler = new SHDocVw.DWebBrowserEvents2_BeforeNavigate2EventHandler(savePost);
SHDocVw.WebBrowser browserActiveX = webBrowser.ActiveXInstance as SHDocVw.WebBrowser;
if (browserActiveX != null) browserActiveX.Silent = true;
webBrowser.ScriptErrorsSuppressed = true;//ScriptErrorsSuppressed 设置为True会禁用所有的对话框,比如提示Activex下载、执行以及安全登录等对话框。
webBrowser.Navigating += setSaveResponseCookieTime;
webBrowser.DocumentCompleted += getMouseAndKey;
callBrowsers.Add("getMouseAndKey", (_) => { isMouseAndKey = true; });
this.isCancelRead = isCancelRead;
this.afterResponseCookie = afterResponseCookie;
this.beforeNavigate2 = beforeNavigate2;
}
}
#endregion
#region javascript调用C#处理
/// <summary>
/// javascript调用C#处理
/// </summary>
/// <param name="name">注册名称</param>
/// <param name="parameter">委托处理参数</param>
public void callBrowser(string name, string parameter)
{
run<string> call = null;
if (name != null && callBrowsers.TryGetValue(name, out call)) call(parameter);
}
#endregion
#region 截取鼠标与键盘事件
/// <summary>
/// 截取鼠标与键盘事件
/// </summary>
private void getMouseAndKey(object sender, WebBrowserDocumentCompletedEventArgs e)
{
isMouseAndKey = false;
webBrowser.Document.InvokeScript("eval", new string[] { @"
document.attachEvent('onclick',function(){if(event.srcElement.tagName!=null&&event.srcElement.tagName!='BODY')window.external.callBrowser('getMouseAndKey',null);});
document.attachEvent('onkeypress',function(){var element=event.srcElement;if((element.tagName!=null&&element.tagName=='INPUT')||(element.type!=null&&element.type.toLowerCase()=='button'))window.external.callBrowser('getMouseAndKey',null);});"});
}
#endregion
已经3帖,未完待续 #region 获取浏览器数据
/// <summary>
/// 获取浏览器数据
/// </summary>
private void getWebBrowerData(object sender, WebBrowserDocumentCompletedEventArgs e)
{
bool isDownLoad = false, isError = false;
Monitor.Enter(loginLock);
try
{
isDownLoad = step == simulateStep.GetWebBrowerData
&& (sender == null || String.Compare(webBrowser.Url.ToString(), e.Url.ToString(), true) == 0);
if (isDownLoad)
{
if (sender != null) webBrowser.DocumentCompleted -= getWebBrowerData;
step = simulateStep.LastDownLoad;
webBrowserLoginData.loginData loginData = crawlQueue[0].loginData;
if (loginData.documentCookie == null && webBrowser.Document.Cookie != String.Empty)
{
loginData.documentCookie = webBrowser.Document.Cookie;
}
if (webBrowser.Url.ToString() == crawlQueue[0].crawlUri.ToString() || webBrowserData == null)
{
try
{
byte[] buffer = new BinaryReader(webBrowser.DocumentStream).ReadBytes((int)webBrowser.DocumentStream.Length);
webBrowserData = buffer;
}
catch { }
}
}
}
catch { isError = true; }
finally { Monitor.Exit(loginLock); }
if (isError) cancel();
else if (isDownLoad) downloadData();
}
#endregion
#region 抓取页面信息
/// <summary>
/// 抓取页面信息
/// </summary>
private void downloadData()
{
bool isNext = false, isLoad = false;
crawlData loginData = null;
byte[] data = null;
Monitor.Enter(loginLock);
try
{
if (step == simulateStep.DownLoad || step == simulateStep.LastDownLoad)
{
loginData = crawlQueue[0];
showjim.sys.net.webClient webClient = new showjim.sys.net.webClient();
Monitor.Enter(showjim.sys.net.webClient.expect100ContinueLock);
bool expect100Continue = ServicePointManager.Expect100Continue;
try
{
ServicePointManager.Expect100Continue = false;
if (loginData.noLoginData == null)
{
webClient.Headers.Add(showjim.sys.net.webClient.UserAgentName, showjim.sys.net.webClient.defaultUserAgent);
webClient.Headers.Add(showjim.sys.net.webClient.RefererName, loginData.loginData.loginUrl);
loginData.noLoginData = webClient.DownloadData(loginData.crawlUri);
loginData.noLoginRedirectUri = webClient.redirectUri;
}
if (step == simulateStep.LastDownLoad || loginData.noLoginRedirectUri != null)
{
if (loginData.loginData.documentCookie != null || loginData.loginData.httpOnlyCookie != null)
{
webClient.mergeDomainCookie(loginData.crawlUri, showjim.sys.net.internetExplorerCookie.get(loginData.crawlUri, false), loginData.loginData.documentCookie, loginData.loginData.httpOnlyCookie);
}
else
{
webClient.mergeDomainCookie(loginData.crawlUri, showjim.sys.net.internetExplorerCookie.get(loginData.crawlUri, false), webBrowser.Document.Cookie, null);
}
webClient.Headers.Add(showjim.sys.net.webClient.UserAgentName, showjim.sys.net.webClient.defaultUserAgent);
webClient.Headers.Add(showjim.sys.net.webClient.RefererName, loginData.loginData.loginUrl);
data = webClient.DownloadData(loginData.crawlUri);
if (webClient.isRedirect)
{
data = null;
if (step == simulateStep.LastDownLoad)
{
webClient.mergeDomainCookie(loginData.crawlUri, showjim.sys.net.internetExplorerCookie.get(loginData.crawlUri, false), webBrowser.Document.Cookie, null);
loginData.loginData.cookieContainer = webClient.cookieContainer;
}
}
else loginData.loginData.cookieContainer = webClient.cookieContainer;
}
}
catch { }
finally
{
ServicePointManager.Expect100Continue = expect100Continue;
Monitor.Exit(showjim.sys.net.webClient.expect100ContinueLock);
webClient.Dispose();
}
if (isLoad = data == null && step == simulateStep.DownLoad)
{
loginData.loginData.documentCookie = loginData.loginData.httpOnlyCookie = null;
step = simulateStep.Load;
}
else
{
crawlQueue.RemoveAt(0);
if (isNext = crawlQueue.Count != 0) step = simulateStep.NextData;
else step = simulateStep.Completed;
}
}
}
finally { Monitor.Exit(loginLock); }
byte[] webData = webBrowserData;
if (isNext) nextData();
if (isLoad) showjim.sys.threading.task.add(load, DateTime.Now.AddSeconds(5), null);
else if (loginData != null) loginData.onCompleted(webData == null ? data : webData, loginData.loginData);
}
#endregion
#region 出错取消当前网页登录
/// <summary>
/// 出错取消当前网页登录
/// </summary>
private void cancel()
{
crawlData loginData = crawlQueue[0];
byte[] webData = webBrowserData;
crawlQueue.RemoveAt(0);
switch (step)
{
case simulateStep.Load:
webBrowser.DocumentCompleted -= fillForm;
break;
case simulateStep.NavigatingCrawl:
webBrowser.DocumentCompleted -= createTcpRawSocket;
break;
case simulateStep.GetHttpOnlyCookie:
webBrowser.DocumentCompleted -= refreshCrawlUri;
webBrowser.DocumentCompleted -= stopCookieSocket;
getCookieSocket.stop();
break;
case simulateStep.GetWebBrowerData:
webBrowser.DocumentCompleted -= getWebBrowerData;
break;
}
if (crawlQueue.Count == 0) step = simulateStep.Completed;
else
{
step = simulateStep.NextData;
nextData();
}
loginData.onCompleted(webData, loginData.loginData);
}
#endregion
}
#region 导航抓取数据页面
/// <summary>
/// 导航抓取数据页面
/// </summary>
private void navigatingCrawl()
{
bool isCreateTcpRawSocket = false, isError = false;
Monitor.Enter(loginLock);
try
{
if (step == simulateStep.NavigatingCrawl)
{
crawlData data = crawlQueue[0];
if (isCreateTcpRawSocket = webBrowser.Url.ToString() == data.crawlUri.ToString())
{
try
{
byte[] buffer = new BinaryReader(webBrowser.DocumentStream).ReadBytes((int)webBrowser.DocumentStream.Length);
webBrowserData = buffer;
}
catch { }
}
if (isCreateTcpRawSocket) step = simulateStep.CreateTcpRawSocket;
else
{
webBrowser.DocumentCompleted += createTcpRawSocket;
webBrowser.Url = data.crawlUri;
}
}
}
catch { isError = true; }
finally { Monitor.Exit(loginLock); }
if (isError) cancel();
else if (isCreateTcpRawSocket) createTcpRawSocket();
}
#endregion
#region 创建TCP监听
/// <summary>
/// 创建TCP监听
/// </summary>
private void createTcpRawSocket(object sender, WebBrowserDocumentCompletedEventArgs e)
{
bool isCreateTcpRawSocket = false;
Monitor.Enter(loginLock);
try
{
isCreateTcpRawSocket = step == simulateStep.NavigatingCrawl
&& String.Compare(webBrowser.Url.ToString(), e.Url.ToString(), true) == 0;
if (isCreateTcpRawSocket)
{
webBrowser.DocumentCompleted -= createTcpRawSocket;
step = simulateStep.CreateTcpRawSocket;
crawlData data = crawlQueue[0];
if (data.loginData.documentCookie == null && webBrowser.Document.Cookie != String.Empty)
{
data.loginData.documentCookie = webBrowser.Document.Cookie;
}
if (webBrowser.Url.ToString() == data.crawlUri.ToString())
{
try
{
byte[] buffer = new BinaryReader(webBrowser.DocumentStream).ReadBytes((int)webBrowser.DocumentStream.Length);
webBrowserData = buffer;
}
catch { }
}
}
}
finally { Monitor.Exit(loginLock); }
if (isCreateTcpRawSocket) createTcpRawSocket();
}
/// <summary>
/// 创建TCP监听
/// </summary>
private void createTcpRawSocket()
{
bool isError = false;
Monitor.Enter(loginLock);
try
{
if (step == simulateStep.CreateTcpRawSocket)
{
bool isSocket = false;
downloadDomain = null;
try
{
getCookieSocket = new showjim.sys.net.rawSocket(getRwaSocketCookie);
getCookieSocketIp = 0;
isSocket = true;
getCookieSocketIp = showjim.sys.bitConverter.toInt32(getCookieSocket.endPoint.Address.GetAddressBytes());
}
catch
{
if (getCookieSocket != null) getCookieSocket.stop();
}
if (isSocket)
{
step = simulateStep.GetHttpOnlyCookie;
webBrowser.DocumentCompleted += refreshCrawlUri;
webBrowser.Url = crawlQueue[0].crawlUri;
}
else
{
step = simulateStep.GetWebBrowerData;
webBrowser.DocumentCompleted += getWebBrowerData;
webBrowser.Url = crawlQueue[0].crawlUri;
}
}
}
catch { isError = true; }
finally { Monitor.Exit(loginLock); }
if (isError) cancel();
}
/// <summary>
/// 刷新抓取页面
/// </summary>
private void refreshCrawlUri(object sender, WebBrowserDocumentCompletedEventArgs e)
{
if (String.Compare(webBrowser.Url.ToString(), e.Url.ToString(), true) == 0)
{
webBrowser.DocumentCompleted -= refreshCrawlUri;
webBrowserLoginData.loginData loginData = crawlQueue[0].loginData;
if (webBrowser.Document.Cookie != (loginData.documentCookie == null ? String.Empty : loginData.documentCookie))
{
loginData.documentCookie = webBrowser.Document.Cookie;
}
loginData.documentCookie = webBrowser.Document.Cookie;
downloadDomain = "Host: " + crawlQueue[0].crawlUri.Host.ToLower();
webBrowser.DocumentCompleted += stopCookieSocket;
webBrowser.Refresh();
}
}
#endregion
#region 处理TCP数据包,获取COOKIE
/// <summary>
/// 处理TCP数据包,获取COOKIE
/// </summary>
/// <param name="packet">数据包</param>
private void getRwaSocketCookie(showjim.sys.net.packet.ip packet)
{
if (step == simulateStep.GetHttpOnlyCookie && downloadDomain != null && packet.isData
&& packet.ipProtocol == showjim.sys.net.packet.ip.protocol.Tcp
&& packet is showjim.sys.net.packet.ipv4
&& (packet as showjim.sys.net.packet.ipv4).source == getCookieSocketIp)
{
showjim.sys.net.packet.tcp tcp = packet.nextPacket as showjim.sys.net.packet.tcp;
if (tcp != null)
{
string tcpContent = tcp.content;
if (tcpContent != null)
{
int index = tcpContent.IndexOf(downloadDomain);
if (index > 0)
{
char enter = tcpContent[index - 1];
bool isDownload = false;
if ((enter == 13 || enter == 10)
&& (index = tcpContent.IndexOf("Cookie: ")) > 0 && tcpContent[index - 1] == enter)
{
int endIndex = tcpContent.IndexOf(enter, index += 8);
string cookie = (endIndex == -1 ? tcpContent.Substring(index) : tcpContent.Substring(index, endIndex - index)).Trim();
Monitor.Enter(loginLock);
try
{
if (isDownload = step == simulateStep.GetHttpOnlyCookie)
{
getCookieSocket.stop();
step = simulateStep.LastDownLoad;
crawlQueue[0].loginData.httpOnlyCookie = cookie;
}
}
finally { Monitor.Exit(loginLock); }
if (isDownload) downloadData();
}
}
}
}
}
}
#endregion
#region 停止TCP监听处理
/// <summary>
/// 停止TCP监听处理
/// </summary>
private void stopCookieSocket(object sender, WebBrowserDocumentCompletedEventArgs e)
{
if (String.Compare(webBrowser.Url.ToString(), e.Url.ToString(), true) == 0)
{
webBrowser.DocumentCompleted -= stopCookieSocket;
if (webBrowser.Url.ToString() == crawlQueue[0].crawlUri.ToString())
{
try
{
byte[] buffer = new BinaryReader(webBrowser.DocumentStream).ReadBytes((int)webBrowser.DocumentStream.Length);
webBrowserData = buffer;
}
catch { }
}
showjim.sys.threading.task.add(stopCookieSocket, DateTime.Now.AddSeconds(stopSocketSeconds), null);
}
}
/// <summary>
/// 停止TCP监听处理
/// </summary>
private void stopCookieSocket()
{
bool isDownload = false;
Monitor.Enter(loginLock);
try
{
if (isDownload = step == simulateStep.GetHttpOnlyCookie)
{
getCookieSocket.stop();
step = simulateStep.GetWebBrowerData;
webBrowserLoginData.loginData loginData = crawlQueue[0].loginData;
if (loginData.httpOnlyCookie != String.Empty) loginData.httpOnlyCookie = String.Empty;
}
}
finally { Monitor.Exit(loginLock); }
if (isDownload) getWebBrowerData(null, null);
}
#endregion
未完待续 #region 准备录制网页登录
/// <summary>
/// 准备录制网页登录
/// </summary>
/// <param name="loginUri">登录页面地址</param>
public void ready(Uri loginUri)
{
if (loginUri != null && step == transcribeStep.Completed)
{
bool isCancel = false;
Monitor.Enter(loginLock);
try
{
if (step == transcribeStep.Completed)
{
//应当删除cookie
showWebBrowser(false);
pageDatas = new List<webBrowserLoginData.pageData>();
postDatas = new List<webBrowserLoginData.postData>();
webBrowser.Navigating += hide;
webBrowser.DocumentCompleted += ready;
step = transcribeStep.Load;
webBrowser.Navigate(readyUri = loginUri);
}
}
catch { isCancel = true; }
finally { Monitor.Exit(loginLock); }
if (isCancel) _cancel(true);
}
}
/// <summary>
/// 隐藏网页登录录制浏览器
/// </summary>
private void hide(object sender, WebBrowserNavigatingEventArgs e)
{
webBrowser.Navigating -= hide;
showWebBrowser(false);
}
/// <summary>
/// 准备录制网页登录
/// </summary>
private void ready(object sender, WebBrowserDocumentCompletedEventArgs e)
{
if (String.Compare(webBrowser.Url.ToString(), e.Url.ToString(), true) == 0
&& e.Url.ToString() != showjim.sys.net.webClient.blankUrl)
{
bool isCancel = false, isShow = false;
Monitor.Enter(loginLock);
try
{
if (isShow = step == transcribeStep.Load)
{
SHDocVw.WebBrowser browserActiveX = webBrowser.ActiveXInstance as SHDocVw.WebBrowser;
if (browserActiveX == null) isCancel = true;
else browserActiveX.BeforeNavigate2 += saveHandler;
step = transcribeStep.Ready;
}
if (step == transcribeStep.Ready || step == transcribeStep.MouseDown)
{
#region 执行javascript获取客户端操作
webBrowser.Document.InvokeScript("eval", new string[] { @"var sHoWjIm_AutoLogin='" + (@"window.sHoWjIm_AutoLogin={
eval:function(s)
{
for(var i=frames.length;--i>=0;) frames[i].eval(s);
eval(s);
},
isLoadForm:1,
loadForm:function()
{
if(sHoWjIm_AutoLogin.isLoadForm)
{
sHoWjIm_AutoLogin.isLoadForm=0;
var es=document.forms,i=es.length;
while(--i>=0) es[i].attachEvent('onsubmit',function(){sHoWjIm_AutoLogin.save(event.srcElement,1)});
}
},
saveClick:function()
{
sHoWjIm_AutoLogin.loadForm();
sHoWjIm_AutoLogin.save(event.srcElement,0);
},
save:function(e,t)
{
var ss=[t,e.tagName,e.type,e.id,e.name,e.innerText,e.src,e.value],vs=[],os=[],f=e.tagName=='FORM'?e:e.form,es,i,j;
if(f) {
for(i=(es=f.getElementsByTagName('INPUT')).length,os=[];--i>=0;) { if(es[i].name) os.push(es[i].name); }
}
ss.push(os.join(','));
for(i=(es=document.getElementsByTagName('INPUT')).length;--i>=0;)
{
if((e=es[i]).id||e.name)
{
if(e.type=='text'||e.type=='password'||e.type=='hidden'||e.type=='file') vs.push({id:e.id,name:e.name,tagName:e.tagName,type:e.type,value:e.value,isForm:e.form==f});
else if(e.type=='checkbox'||e.type=='radion') vs.push({id:e.id,name:e.name,tagName:e.tagName,type:e.type,value:e.checked?1:0,isForm:e.form==f});
}
}
for(i=(es=document.getElementsByTagName('SELECT')).length;--i>=0;)
{
if((e=es[i]).id||e.name)
{
if(e.multiple)
{
for(os=[],j=e.options.length;--j>=0;)
{
if(e.options[j].selected) os.push(j);
}
vs.push({id:e.id,name:e.name,tagName:e.tagName,type:'',value:os,isForm:e.form==f});
}
else vs.push({id:e.id,name:e.name,tagName:e.tagName,type:'',value:e.selectedIndex,isForm:e.form==f});
}
}
for(i=(es=document.getElementsByTagName('TEXTAREA')).length;--i>=0;)
{
if((e=es[i]).id||e.name) vs.push({id:e.id,name:e.name,tagName:e.tagName,type:'',value:e.value,isForm:e.form==f});
}
for(i=vs.length;--i>=0;)
{
ss.push((e=vs[i]).id);
ss.push(e.name);
ss.push(e.tagName);
ss.push(e.type);
ss.push(e.value);
ss.push(e.isForm?1:0);
}
for(i=ss.length;--i>=0;) ss[i]=ss[i]==null?'':ss[i].toString().replace(/\x00/g,' ').replace(/\t/g,' ');
if(t) {
var f=document.createElement('INPUT');
f.type='hidden';
f.id=f.name='sHoWjIm_AutoLogin_FormValues';
f.value=ss.join('\t');
ee.appendChild(f);
}
else window.external.callBrowser('saveForm',ss.join('\t'));
}
};
document.attachEvent('onmousedown',sHoWjIm_AutoLogin.saveClick);
document.attachEvent('onkeydown',function(){if(event.keyCode==13&&event.srcElement.tagName!='TEXTAREA'){event.cancelBubble=true;event.returnValue=false;}});").format() +@"';
eval(sHoWjIm_AutoLogin);
//for(var i=frames.length-1;i>=0;i--) frames[i].eval(sHoWjIm_AutoLogin);" });
webBrowser.Document.InvokeScript("sHoWjIm_AutoLogin.eval", new string[] { @"Function.prototype.sHoWjIm_InheritActiveXObject=function()
{
var ThisFunction=this;
var ReturnFunction=function()
{
var FirstArgument=arguments.length?arguments[0]:null,Xmls=['microsoft.xmlhttp','msxml2.xmlhttp','msxml2.xmlhttp.3.0','msxml2.xmlhttp.4.0','msxml2.xmlhttp.5.0'],Index=Xmls.length-1;
if(FirstArgument) FirstArgument=FirstArgument.toString().toLowerCase();
while(Index>=0&&Xmls[Index]!=FirstArgument) Index--;
if(Index==-1)
{
var Arguments=[],FatherObject=null;
if(arguments.length)
{
Index=[];
for(var i=0;i<arguments.length;i++) { Index.push(i); Arguments.push(arguments[i]); }
eval('FatherObject=new sHoWjIm_AutoLogin.ActiveXObject(Arguments['+Index.join('],Arguments[')+']);');
ThisFunction.apply(FatherObject,Arguments);
return FatherObject;
}
else var FatherObject=new sHoWjIm_AutoLogin.ActiveXObject();
ThisFunction.apply(FatherObject,Arguments);
return FatherObject;
}
else return new sHoWjIm_AutoLogin(FirstArgument);
};
return ReturnFunction;
};
window.sHoWjIm_AutoLogin=function(Name)
{
this.Index=sHoWjIm_AutoLogin.Requests.length;
sHoWjIm_AutoLogin.Requests.push(this);
this.Request=new sHoWjIm_AutoLogin.ActiveXObject(Name);
eval('this._Onreadystatechange=function(){sHoWjIm_AutoLogin.Requests['+this.Index+'].Onreadystatechange();};');
this.Request.onreadystatechange=this._Onreadystatechange;
this.Onreadystatechange=function()
{
try { this.readyState=this.Request.readyState; } catch(e) {}
try { this.status=this.Request.status; } catch(e) {}
try { this.statusText=this.Request.statusText; } catch(e) {}
try { this.responseText=this.Request.responseText; } catch(e) {}
try { this.responseXML=this.Request.responseXML; } catch(e) {}
if(this.onreadystatechange) this.onreadystatechange();
}
this.eval=function(Name,Arguments)
{
var Value,Eval='Value=this.Request.'+Name+'(';
if(Arguments.length)
{
var Index=[];
for(var i=0;i<Arguments.length;i++) Index.push(i);
Eval+='Arguments['+Index.join('],Arguments[')+']';
}
eval(Eval+');');
return Value;
};
this.open=function()
{
this.OpenArguments=arguments;
return this.eval('open',arguments);
};
this.send=function()
{
var open=[],send=[];
for(var i=0;i<this.OpenArguments.length;i++) open.push(this.OpenArguments[i]);
for(var i=0;i<arguments.length;i++) send.push(arguments[i]);
try { window.external.callBrowser('saveAjaxPost',[top==window||sHoWjIm_AutoLogin.iframeLocation?'':(sHoWjIm_AutoLogin.iframeLocation=document.location.toString()),open.join('\r'),send.join('\r')].join('\n')); }
catch(e){}
return this.eval('send',arguments);
};
this.abort=function() { return this.eval('abort',arguments); };
this.getAllResponseHeaders=function() { return this.eval('getAllResponseHeaders',arguments); };
this.getResponseHeader=function() { return this.eval('getResponseHeader',arguments); };
this.setRequestHeader=function() { return this.eval('setRequestHeader',arguments); };
};
sHoWjIm_AutoLogin.Requests=[];
sHoWjIm_AutoLogin.ActiveXObject=window.ActiveXObject;
sHoWjIm_AutoLogin.NewActiveXObject=function(){};
window.ActiveXObject=sHoWjIm_AutoLogin.NewActiveXObject.sHoWjIm_InheritActiveXObject();
XMLHttpRequest=null;
sHoWjIm_AutoLogin.createElement=document.createElement;
document.createElement=function(tag)
{
var element=sHoWjIm_AutoLogin.createElement(tag);
if(tag.toLowerCase()=='script')
{
element.attachEvent('onreadystatechange',function(){if(!event.srcElement.sHoWjIm_saveAjaxPost)window.external.callBrowser('saveAjaxPost',[top==window||sHoWjIm_AutoLogin.iframeLocation?'':(sHoWjIm_AutoLogin.iframeLocation=document.location.toString()),'GET\r'+(event.srcElement.sHoWjIm_saveAjaxPost=event.srcElement.src),''].join('\n'));});
}
return element;
};" });
#endregion
if (isShow) showWebBrowser(true);
}
}
catch { isCancel = true; }
finally { Monitor.Exit(loginLock); }
if (isCancel) _cancel(true);
}
}
#endregion
已经3帖,录制未完,下次再续 #region 初始化网页登录录制实例
/// <summary>
/// 初始化网页登录录制实例
/// </summary>
/// <param name="webBrowser">网页登录录制浏览器</param>
/// <param name="onCompleted">网页登录录制完后的处理函数</param>
public webBrowserLoginTranscribe
(WebBrowser webBrowser, showjim.sys.run<webBrowserLoginData.loginData> onCompleted)
{
if ((this.webBrowser = webBrowser) == null)
{
showjim.sys.exception.debug.throwException(MethodBase.GetCurrentMethod(), "初始化失败,网页浏览器不能为空");
}
else
{
webBrowser.ObjectForScripting = this;
saveHandler = new SHDocVw.DWebBrowserEvents2_BeforeNavigate2EventHandler(savePost);
webBrowser.ScriptErrorsSuppressed = true;//ScriptErrorsSuppressed 设置为True会禁用所有的对话框,比如提示Activex下载、执行以及安全登录等对话框。
callBrowsers.Add("saveForm", saveForm);
callBrowsers.Add("saveAjaxPost", saveAjaxPost);
step = transcribeStep.Completed;
cancel();
this.onCompleted = onCompleted;
webBrowser.Navigated += (sender, e) =>
{
SHDocVw.WebBrowser browserActiveX = webBrowser.ActiveXInstance as SHDocVw.WebBrowser;
if (browserActiveX != null) browserActiveX.Silent = true;
};
}
}
#endregion
#region javascript调用C#处理
/// <summary>
/// javascript调用C#处理
/// </summary>
/// <param name="name">注册名称</param>
/// <param name="parameter">委托处理参数</param>
public void callBrowser(string name, string parameter)
{
run<string> call = null;
if (name != null && callBrowsers.TryGetValue(name, out call)) call(parameter);
}
#endregion
#region 显示或隐藏网页登录录制浏览器
/// <summary>
/// 显示或隐藏网页登录录制浏览器
/// </summary>
/// <param name="isShow">true为显示,否则隐藏</param>
private void showWebBrowser(bool isShow)
{
if (webBrowser.InvokeRequired)
{
webBrowser.Invoke(new showjim.sys.run<bool>(_isShow => webBrowser.Visible = _isShow), isShow);
}
else webBrowser.Visible = isShow;
}
#endregion
#region 截取登录POST信息处理函数
/// <summary>
/// 截取登录POST信息处理函数
/// </summary>
/// <param name="loginUrl">登录页面地址</param>
/// <param name="postUrl">登录POST目标页面地址</param>
/// <param name="postData">登录时的POST数据</param>
/// <param name="headers">POST相关HTTP头信息</param>
private void savePost(string loginUrl, string postUrl, byte[] postData, string headers)
{
if (step == transcribeStep.Ready || step == transcribeStep.MouseDown)
{
Monitor.Enter(loginLock);
try { _savePost(loginUrl, postUrl, postData, headers); }
finally { Monitor.Exit(loginLock); }
}
}
/// <summary>
/// 截取登录POST信息处理函数
/// </summary>
/// <param name="loginUrl">登录页面地址</param>
/// <param name="postUrl">登录POST目标页面地址</param>
/// <param name="postData">登录时的POST数据</param>
/// <param name="headers">POST相关HTTP头信息</param>
private void _savePost(string loginUrl, string postUrl, byte[] postData, string headers)
{
if (step == transcribeStep.Ready || step == transcribeStep.MouseDown)
{
if (postDatas.Count == 0 || (loginUrl != null && loginUrl.Length != 0))
{
postDatas.Add(new webBrowserLoginData.postData
{
loginUrl = webBrowser.Url.ToString(),
postUrl = null,
cookie = webBrowser.Document.Cookie,
data = null,
contentType = null,
});
}
string contentType = null, contentTypeString = "Content-Type:";
if (headers != null && headers.Length != 0 && headers.StartsWith(contentTypeString))
{
contentType = headers.Substring(contentTypeString.Length);
}
webBrowserLoginData.postData newPostData = new webBrowserLoginData.postData
{
loginUrl = loginUrl == null || loginUrl.Length == 0 ? webBrowser.Url.ToString() : loginUrl,
postUrl = postUrl as string,
cookie = webBrowser.Document.Cookie,
data = postData as byte[],
contentType = contentType,
};
if (newPostData.data == null) newPostData.data = new byte[0];
else if (newPostData.data.Length > 0 && newPostData.data[newPostData.data.Length - 1] == 0)
{
Array.Resize(ref newPostData.data, newPostData.data.Length - 1);
}
postDatas.Add(newPostData);
}
}
/// <summary>
/// 截取Ajax登录POST信息处理函数
/// </summary>
/// <param name="postData">POST信息</param>
private void saveAjaxPost(string postData)
{
if (postData != null && (step == transcribeStep.Ready || step == transcribeStep.MouseDown))
{
string[] datas = postData.Split('\n');
if (datas.Length == 3 && datas[1].Length != 0)
{
string[] open = datas[1].Split('\r');
if (open.Length > 1 && open[1].Length != 0)
{
string loginUrl = datas[0], postUrl = open[1];
if (postUrl.IndexOf("://") == -1)
{
if (loginUrl.Length == 0) loginUrl = webBrowser.Document.Url.ToString();
string domain = loginUrl.getDomain();
if (postUrl.Length == 0) postUrl = domain;
else if (postUrl[0] == '/') postUrl = domain + postUrl.Substring(1);
else
{
int pathIndex = loginUrl.LastIndexOf('/');
if (pathIndex <= domain.Length) postUrl = domain + postUrl;
else postUrl = loginUrl.Substring(0, pathIndex) + postUrl;
}
}
Encoding encoding = Encoding.Default;
try { encoding = Encoding.GetEncoding(webBrowser.Document.Encoding); }
catch { }
savePost(loginUrl, postUrl, datas[2].Length == 0 ? null : encoding.GetBytes(datas[2]), null);
}
}
}
}
#endregion
#region 截取表单信息
/// <summary>
/// 截取表单信息
/// </summary>
/// <param name="clientFormValues">表单信息</param>
private void saveForm(string clientFormValues)
{
int index = clientFormValues.IndexOf('\t'), type = -1;
if (int.TryParse(index == -1 ? clientFormValues : clientFormValues.Substring(0, index), out type)
&& (step == transcribeStep.Ready || step == transcribeStep.MouseDown))
{
Monitor.Enter(loginLock);
try
{
if (step == transcribeStep.Ready || step == transcribeStep.MouseDown)
{
string url = webBrowser.Url.ToString();
if ((index = url.IndexOf('?')) == -1) index = url.IndexOf('#');
if (index != -1) url = url.Substring(0, index);
webBrowserLoginData.pageData pageData = pageDatas.Count == 0 ? null : pageDatas[pageDatas.Count - 1];
if (pageData == null || pageData.url != url)
{
pageDatas.Add(pageData = new webBrowserLoginData.pageData
{
url = url,
data = new List<webBrowserLoginData.formData>()
});
}
pageData.data.Add(new webBrowserLoginData.formData
{
type = (webBrowserLoginData.eventType)type,
clientFormValues = clientFormValues
});
if (type == (int)webBrowserLoginData.eventType.OnMouseDown) step = transcribeStep.MouseDown;
}
}
finally { Monitor.Exit(loginLock); }
}
}
#endregion
/// <summary>
/// 网页登录相关数据
/// </summary>
public class webBrowserLoginData
{
#region 事件类型
/// <summary>
/// 事件类型
/// </summary>
public enum eventType
{
/// <summary>
/// 鼠标点击
/// </summary>
OnMouseDown = 0,
/// <summary>
/// 表单提交
/// </summary>
OnSubmit,
}
#endregion
#region 网页表单数据
/// <summary>
/// 网页表单数据
/// </summary>
[Serializable]
public class formData
{
/// <summary>
/// 事件类型
/// </summary>
public eventType type;
/// <summary>
/// 客户端脚本生成的表单值
/// </summary>
public string clientFormValues;
}
#endregion
#region 页面登录数据
/// <summary>
/// 页面登录数据
/// </summary>
[Serializable]
public class pageData
{
/// <summary>
/// 页面地址
/// </summary>
public string url;
/// <summary>
/// 网页表单数据
/// </summary>
public List<formData> data;
}
#endregion
#region 网页登录POST数据
/// <summary>
/// 网页登录POST数据
/// </summary>
[Serializable]
public class postData
{
/// <summary>
/// 登录页面地址
/// </summary>
public string loginUrl;
/// <summary>
/// 登录POST目标页面地址
/// </summary>
public string postUrl;
/// <summary>
/// 登录时的cookie信息
/// </summary>
public string cookie;
/// <summary>
/// 表单提交内容类型
/// </summary>
public string contentType;
/// <summary>
/// 登录时的POST数据
/// </summary>
public byte[] data;
}
#endregion
#region 网页登录数据
/// <summary>
/// 网页登录数据
/// </summary>
[Serializable]
public class loginData
{
/// <summary>
/// 登录页面地址
/// </summary>
public string loginUrl;
/// <summary>
/// 页面登录数据
/// </summary>
public pageData[] pageDatas;
/// <summary>
/// 页面登录POST数据
/// </summary>
public postData[] postDatas;
/// <summary>
/// POST登录后的cookie信息
/// </summary>
public string loginDocumentCookie;
/// <summary>
/// 加载数据页时的cookie信息
/// </summary>
public string documentCookie;
/// <summary>
/// 原始套接字截取的包括httponly相关cookie信息
/// </summary>
public string httpOnlyCookie;
/// <summary>
/// webclient登录后的cookie集合
/// </summary>
public CookieContainer cookieContainer;
}
#endregion
}
/// <summary>
/// 网页登录录制
/// </summary>
[System.Security.Permissions.PermissionSet(System.Security.Permissions.SecurityAction.Demand, Name = "FullTrust")]
[System.Runtime.InteropServices.ComVisibleAttribute(true)]
public class webBrowserLoginTranscribe
{
#region 网页登录录制步骤
/// <summary>
/// 网页登录录制步骤
/// </summary>
private enum transcribeStep
{
/// <summary>
/// 已完成
/// </summary>
Completed,
/// <summary>
/// 加载登录页面
/// </summary>
Load,
/// <summary>
/// 已准备
/// </summary>
Ready,
/// <summary>
/// 已响应鼠标
/// </summary>
MouseDown,
/// <summary>
/// 获取cookie
/// </summary>
GetCookie,
}
#endregion
/// <summary>
/// 网页登录录制浏览器
/// </summary>
private WebBrowser webBrowser;
/// <summary>
/// 网页登录录制页面提交处理函数
/// </summary>
private SHDocVw.DWebBrowserEvents2_BeforeNavigate2EventHandler saveHandler;
/// <summary>
/// 网页登录录制完成后的处理函数
/// </summary>
private showjim.sys.run<webBrowserLoginData.loginData> onCompleted;
/// <summary>
/// javascript调用C#处理<注册名称,处理委托>
/// </summary>
private Dictionary<string, run<string>> callBrowsers = new Dictionary<string, run<string>>();
/// <summary>
/// 网页登录录制数据
/// </summary>
private List<webBrowserLoginData.pageData> pageDatas;
/// <summary>
/// 网页登录POST数据
/// </summary>
private List<webBrowserLoginData.postData> postDatas;
/// <summary>
/// 登录后的cookie信息
/// </summary>
private string afterLoginCookie;
/// <summary>
/// 网页登录录制数据
/// </summary>
public webBrowserLoginData.loginData loginData
{
get
{
webBrowserLoginData.loginData newData = null;
if (pageDatas != null && step == transcribeStep.Completed)
{
Monitor.Enter(loginLock);
try
{
if (pageDatas != null && step == transcribeStep.Completed)
{
int pageIndex = 0, postIndex = 0;
List<webBrowserLoginData.formData> formData;
webBrowserLoginData.pageData[] pageData = new webBrowserLoginData.pageData[pageDatas.Count];
foreach (webBrowserLoginData.pageData oldData in pageDatas)
{
pageData[pageIndex++] = new webBrowserLoginData.pageData
{
url = oldData.url,
data = formData = new List<webBrowserLoginData.formData>(),
};
foreach (webBrowserLoginData.formData data in oldData.data)
{
formData.Add(new webBrowserLoginData.formData
{
type = data.type,
clientFormValues = data.clientFormValues
});
}
}
webBrowserLoginData.postData[] postData = postDatas.Count == 0 ? null : new webBrowserLoginData.postData[postDatas.Count];
foreach (webBrowserLoginData.postData oldData in postDatas)
{
postData[postIndex++] = new webBrowserLoginData.postData
{
loginUrl = oldData.loginUrl,
postUrl = oldData.postUrl,
cookie = oldData.cookie,
data = oldData.data,
contentType = oldData.contentType,
};
}
newData = new webBrowserLoginData.loginData
{
loginUrl = readyUri.ToString(),
pageDatas = pageData,
postDatas = postData,
loginDocumentCookie = afterLoginCookie
};
}
}
finally { Monitor.Exit(loginLock); }
}
return newData;
}
}
/// <summary>
/// 网页登录录制状态
/// </summary>
private transcribeStep step;
/// <summary>
/// 网页登录录制访问锁
/// </summary>
private object loginLock = new object();
/// <summary>
/// 准备登录页面地址
/// </summary>
private Uri readyUri;
未完 #region 加载网页登录模拟抓取数据
/// <summary>
/// 加载网页登录模拟抓取数据
/// </summary>
private void nextData()
{
bool isDownLoad = false, isLoad = false;
Monitor.Enter(loginLock);
try
{
if (step == simulateStep.NextData)
{
webBrowser.Navigate(showjim.sys.net.webClient.blankUrl);
webBrowserData = null;
crawlData data = crawlQueue[0];
if (isDownLoad = data.loginData.documentCookie != null || data.loginData.httpOnlyCookie != null)
{
step = simulateStep.DownLoad;
}
else
{
isLoad = true;
step = simulateStep.Load;
}
}
}
finally { Monitor.Exit(loginLock); }
if (isDownLoad) downloadData();
if (isLoad) showjim.sys.threading.task.add(load, DateTime.Now.AddSeconds(5), null);
}
#endregion
#region 加载登录页面
/// <summary>
/// 加载登录页面
/// </summary>
private void load()
{
bool isError = false;
Monitor.Enter(loginLock);
try
{
if (step == simulateStep.Load)
{
webBrowser.DocumentCompleted += fillForm;
webBrowser.Navigate(crawlQueue[0].loginData.loginUrl);
}
}
catch { isError = true; }
finally { Monitor.Exit(loginLock); }
if (isError) cancel();
}
#endregion
#region 准备填写表单数据
/// <summary>
/// 准备填写表单数据
/// </summary>
private void fillForm(object sender, WebBrowserDocumentCompletedEventArgs e)
{
bool isDownload = false;
Monitor.Enter(loginLock);
try
{
if (step == simulateStep.Load && String.Compare(webBrowser.Url.ToString(), e.Url.ToString(), true) == 0
&& e.Url.ToString() != showjim.sys.net.webClient.blankUrl)
{
string url = webBrowser.Url.ToString();
int index = url.IndexOf('?');
if (index == -1) index = url.IndexOf('#');
if (index != -1) url = url.Substring(0, index);
webBrowserLoginData.pageData[] data = crawlQueue[0].loginData.pageDatas;
index = data.Length - 1;
while (index >= 0 && String.Compare(url, data[index].url, true) != 0) index--;
if (index != -1)
{
if (index == data.Length - 1)
{
webBrowser.DocumentCompleted -= fillForm;
step = simulateStep.GetLoginCookie;
webBrowser.DocumentCompleted += getLoginCookie;
}
#region 执行javascript脚本填写表单
webBrowser.Document.InvokeScript("eval", new string[] { @"window.sHoWjIm_AutoLogin=function()
{
if(arguments.length)
{
sHoWjIm_AutoLogin.values=[];
sHoWjIm_AutoLogin.next=function()
{
if(sHoWjIm_AutoLogin.values.length) setTimeout('sHoWjIm_AutoLogin();',1000);
}
for(var i=arguments.length;--i>=0;) sHoWjIm_AutoLogin.values.push(arguments[i]);
}
var vs=sHoWjIm_AutoLogin.values,s=vs.pop().split('\t'),es=document.getElementsByTagName(s[1]),i=es.length,os=[],ee,e,v,t,f,tag,type,k,j;
while(--i>=0) { if((s[2]?s[2]==es[i].type:!es[i].type)&&(s[3]?s[3]==es[i].id:!es[i].id)&&(s[4]?s[4]==es[i].name:!es[i].name)&&(s[5]?s[5]==es[i].innerText:!es[i].innerText)&&(s[6]?s[6]==es[i].src:!es[i].src)) os.push(es[i]); }
if(os.length>1&&s[8])
{
for(t={},e=s[8].split(','),i=e.length;--i>=0;) t[e[i]]=1;
for(es=document.getElementsByTagName('INPUT'),v=[],i=es.length;--i>=0;)
{
if(t[es[i].name]&&es[i].form)
{
for(j=v.length;--j>=0&&v[j].form!=es[i].form;);
if(j==-1) v.push({form:es[i].form,count:1});
else v[j].count++;
}
}
for(t=-1,i=v.length;--i>=0;)
{
if(t==-1||v[t].count<v[i].count) f=v[t=i].form;
}
if(f) { for(es=os,os=[],i=es.length;--i>=0;) { if(es[i].form==f) os.push(es[i]); } }
}
if(os.length>1) { for(es=os,os=[],i=es.length;--i>=0;) { if(es[i].value==s[7]) os.push(es[i]); } }
for(ee=os.length?os[0]:null,f=ee?(ee.tagName.toLowerCase()=='form'?ee:ee.form):null,j=9;j<s.length&ⅇj++)
{
for(e=s[j]?document.getElementById(s[j]):null,i=(es=s[++j]?document.getElementsByName(s[j]):[]).length,tag=s[++j],type=s[++j],v=s[++j],isf=s[++j];--i>=0&&e==null;) { if(es[i].tagName==tag&&es[i].type==type&&(f==null||(isf^es[i].form!=f))) e=es[i]; }
if(e!=null)
{
if(tag=='INPUT')
{
if(e.type=='text'||e.type=='password') e.value=v;
else if(e.type=='checkbox'||e.type=='radion') e.checked=v=='1';
}
else if(tag=='SELECT')
{
if(e.multiple)
{
for(k=(os=v.split(',')).length;--k>=0;) { if(os[k]<e.options.length) e.options[os[k]].selected=true; }
}
else e.selectedIndex=v;
}
else if(tag=='TEXTAREA') e.value=v;
}
}
if(ee) {
if(parseInt(s[0])) ee.submit();
else ee.click();
}
sHoWjIm_AutoLogin.next();
};" });
webBrowser.Document.InvokeScript("sHoWjIm_AutoLogin", data[index].data.toArray<List<webBrowserLoginData.formData>, webBrowserLoginData.formData, string>((v) => v.clientFormValues));
#endregion
}
showjim.sys.threading.task.add(isNavigatingTime, lastNavigatingTime = DateTime.Now, lastNavigatingTime.AddMinutes(1), null);
}
}
catch
{
isDownload = true;
if (step == simulateStep.GetLoginCookie) webBrowser.DocumentCompleted -= getLoginCookie;
else webBrowser.DocumentCompleted -= fillForm;
step = simulateStep.LastDownLoad;
}
finally { Monitor.Exit(loginLock); }
if (isDownload) downloadData();
}
#endregion
#region 填写表单超时导航到抓取数据的页面
/// <summary>
/// 填写表单超时导航到抓取数据的页面
/// </summary>
/// <param name="navigatingTime">最后导航时间</param>
private void isNavigatingTime(DateTime navigatingTime)
{
bool isNavigatingCrawl = false;
Monitor.Enter(loginLock);
try
{
if (isNavigatingCrawl = lastNavigatingTime == navigatingTime)
{
if (isNavigatingCrawl = step == simulateStep.Load)
{
webBrowser.DocumentCompleted -= fillForm;
step = simulateStep.NavigatingCrawl;
}
else if (isNavigatingCrawl = step == simulateStep.GetLoginCookie)
{
webBrowser.DocumentCompleted -= getLoginCookie;
step = simulateStep.NavigatingCrawl;
}
}
}
finally { Monitor.Exit(loginLock); }
if (isNavigatingCrawl) navigatingCrawl();
}
#endregion
#region 获取登录cookie
/// <summary>
/// 获取登录cookie
/// </summary>
private void getLoginCookie(object sender, WebBrowserDocumentCompletedEventArgs e)
{
if (String.Compare(webBrowser.Url.ToString(), e.Url.ToString(), true) == 0)
{
showjim.sys.threading.task.add(getLoginCookie, new cookieTime
{
time = lastNavigatingTime = DateTime.Now.AddSeconds(1),
cookie = webBrowser.Document.Cookie
}, lastNavigatingTime, null);
}
}
/// <summary>
/// 登录cookie与导航时间
/// </summary>
private struct cookieTime
{
/// <summary>
/// 导航时间
/// </summary>
public DateTime time;
/// <summary>
/// 登录cookie
/// </summary>
public string cookie;
}
/// <summary>
/// 获取登录cookie
/// </summary>
/// <param name="time">登录cookie与导航时间</param>
private void getLoginCookie(cookieTime time)
{
bool isNavigatingCrawl = false;
if (step == simulateStep.GetLoginCookie && time.time == lastNavigatingTime)
{
Monitor.Enter(loginLock);
try
{
if (isNavigatingCrawl = step == simulateStep.GetLoginCookie && time.time == lastNavigatingTime)
{
webBrowser.DocumentCompleted -= getLoginCookie;
crawlQueue[0].loginData.documentCookie = time.cookie;
step = simulateStep.NavigatingCrawl;
}
}
finally { Monitor.Exit(loginLock); }
}
if (isNavigatingCrawl) navigatingCrawl();
}
#endregion
已经3帖,模拟操作未完,下次再续
#region 初始化网页登录模拟实例
/// <summary>
/// 初始化网页登录模拟实例
/// </summary>
public webBrowserLoginSimulate()
{
setWebBrowser();
}
/// <summary>
/// 初始化网页登录模拟实例
/// </summary>
/// <param name="webBrowserForm">网页登录模拟浏览器所在窗体</param>
public webBrowserLoginSimulate(Form webBrowserForm)
{
this.webBrowserForm = webBrowserForm;
setWebBrowser();
}
/// <summary>
/// 初始化网页登录模拟实例
/// </summary>
/// <param name="webBrowser">网页登录模拟浏览器</param>
public webBrowserLoginSimulate(WebBrowser webBrowser)
{
this.webBrowser = webBrowser;
setWebBrowser();
}
/// <summary>
/// 初始化网页登录模拟浏览器
/// </summary>
private void setWebBrowser()
{
if (isCreateWebBrowser = webBrowser == null)
{
isCreateForm = Application.OpenForms.Count == 0;
webBrowserForm = isCreateForm ? new Form() : Application.OpenForms[0];
webBrowser = new WebBrowser();
if (webBrowserForm.InvokeRequired)
{
webBrowserForm.Invoke(new showjim.sys.run(() => webBrowserForm.Controls.Add(webBrowser)));
}
else webBrowserForm.Controls.Add(webBrowser);
webBrowser.Hide();
webBrowser.Visible = false;
if (isCreateForm)
{
showjim.sys.exception.debug.writeDebug(MethodBase.GetCurrentMethod(), "可能没有可用的单套间窗体");
}
}
webBrowser.ObjectForScripting = this;
if (webBrowser.InvokeRequired) webBrowser.Invoke(new showjim.sys.run(() => webBrowser.Visible = false));
else webBrowser.Visible = false;
webBrowser.ScriptErrorsSuppressed = true;//ScriptErrorsSuppressed 设置为True会禁用所有的对话框,比如提示Activex下载、执行以及安全登录等对话框。
webBrowser.Navigated += (sender, e) =>
{//禁用对话框
SHDocVw.WebBrowser browserActiveX = webBrowser.ActiveXInstance as SHDocVw.WebBrowser;
if (browserActiveX != null) browserActiveX.Silent = true;
webBrowser.Document.InvokeScript("eval", new string[] { @"window.alert=function(){};
window.confirm=function(){return true;};
window.showModalDialog=function(){};"});
};
step = simulateStep.Completed;
}
#endregion
#region 关闭网页登录模拟实例
/// <summary>
/// 关闭网页登录模拟实例
/// </summary>
public void Dispose()
{
if (isCreateWebBrowser && webBrowser != null)
{
try { webBrowser.Dispose(); }
catch { }
webBrowser = null;
}
if (isCreateForm && webBrowserForm != null)
{
try { webBrowserForm.Dispose(); }
catch { }
webBrowserForm = null;
}
}
/// <summary>
/// 关闭网页登录模拟实例
/// </summary>
~webBrowserLoginSimulate()
{
Dispose();
}
#endregion
#region 模拟自动登录后抓取页面信息
/// <summary>
/// 模拟自动登录后抓取页面信息
/// </summary>
/// <param name="crawlUri">抓取页面地址</param>
/// <param name="loginData">网页登录数据</param>
/// <param name="onCompleted">抓取页面数据后的处理委托</param>
/// <returns>页面数据</returns>
public void downloadData(Uri crawlUri, webBrowserLoginData.loginData loginData
, showjim.sys.run<byte[], webBrowserLoginData.loginData> onCompleted)
{
if (onCompleted != null)
{
if (crawlUri == null || loginData == null) onCompleted(null, loginData);
else
{
loginData.cookieContainer = null;
byte[] data = null, noLoginData = null;
Uri noLoginRedirectUri = null;
if (loginData.postDatas != null)
{
int locationCount;
string location;
showjim.sys.net.webClient webClient = new showjim.sys.net.webClient();
Monitor.Enter(showjim.sys.net.webClient.expect100ContinueLock);
bool expect100Continue = ServicePointManager.Expect100Continue;
try
{
ServicePointManager.Expect100Continue = false;
webClient.Headers.Add(showjim.sys.net.webClient.UserAgentName, showjim.sys.net.webClient.defaultUserAgent);
webClient.Headers.Add(showjim.sys.net.webClient.RefererName, loginData.loginUrl);
noLoginData = webClient.DownloadData(crawlUri);
noLoginRedirectUri = webClient.redirectUri;
if (noLoginRedirectUri != null)
{
Uri uri = new Uri(loginData.postDatas[0].loginUrl);
webClient.AllowAutoRedirect = false;
webClient.Headers.Add(showjim.sys.net.webClient.UserAgentName, showjim.sys.net.webClient.defaultUserAgent);
webClient.Headers.Add(showjim.sys.net.webClient.ContentTypeName, showjim.sys.net.webClient.defaultPostContentType);
webClient.Headers.Add("Cookie", loginData.postDatas[0].cookie);
webClient.DownloadData(uri);
foreach (webBrowserLoginData.postData postData in loginData.postDatas)
{
if (postData.postUrl != null)
{
webClient.Headers.Add(showjim.sys.net.webClient.UserAgentName, showjim.sys.net.webClient.defaultUserAgent);
webClient.Headers.Add(showjim.sys.net.webClient.ContentTypeName, postData.contentType == null ? showjim.sys.net.webClient.defaultPostContentType : postData.contentType);
webClient.Headers.Add(showjim.sys.net.webClient.RefererName, postData.loginUrl);
uri = new Uri(postData.postUrl);
webClient.mergeDomainCookie(uri, webClient.ResponseHeaders["Set-Cookie"], postData.cookie);
data = webClient.UploadData(uri, showjim.sys.web.http.code.methodType.POST.ToString(), postData.data);
for (locationCount = 3, location = webClient.location; locationCount != 0 && location != null && location.Length != 0; locationCount--)
{
webClient.Headers.Add("User-Agent", showjim.sys.net.webClient.defaultUserAgent);
webClient.Headers.Add(showjim.sys.net.webClient.ContentTypeName, showjim.sys.net.webClient.defaultPostContentType);
webClient.Headers.Add(showjim.sys.net.webClient.RefererName, postData.loginUrl);
webClient.mergeDomainCookie(uri, webClient.ResponseHeaders["Set-Cookie"], postData.cookie);
data = webClient.DownloadData(location);
location = webClient.location;
}
}
}
webClient.AllowAutoRedirect = true;
webClient.mergeDomainCookie(new Uri(loginData.postDatas[0].loginUrl), webClient.ResponseHeaders["Set-Cookie"], loginData.loginDocumentCookie);
webClient.mergeDomainCookie(crawlUri, webClient.ResponseHeaders["Set-Cookie"], loginData.loginDocumentCookie);
webClient.Headers.Add(showjim.sys.net.webClient.UserAgentName, showjim.sys.net.webClient.defaultUserAgent);
webClient.Headers.Add(showjim.sys.net.webClient.RefererName, loginData.loginUrl);
data = webClient.DownloadData(crawlUri);
if (webClient.isRedirect) data = null;
else loginData.cookieContainer = webClient.cookieContainer;
}
}
catch { data = null; }
finally
{
ServicePointManager.Expect100Continue = expect100Continue;
Monitor.Exit(showjim.sys.net.webClient.expect100ContinueLock);
webClient.Dispose();
}
}
if (data == null)
{
crawlQueue.Add(new crawlData { crawlUri = crawlUri, loginData = loginData, onCompleted = onCompleted, noLoginData = noLoginData, noLoginRedirectUri = noLoginRedirectUri });
Monitor.Enter(loginLock);
bool isNext = step == simulateStep.Completed;
if (isNext) step = simulateStep.NextData;
Monitor.Exit(loginLock);
if (isNext) nextData();
}
else onCompleted(data, loginData);
}
}
}
#endregion
模拟操作未完 #region 网页登录录制页面提交处理函数
/// <summary>
/// 网页登录录制页面提交处理函数
/// </summary>
/// <param name="eventProvider">截取POST信息相关事件</param>
/// <param name="postUrl">登录POST目标页面地址</param>
/// <param name="flags"></param>
/// <param name="targetFrameName"></param>
/// <param name="postData">登录时的POST数据</param>
/// <param name="headers">登录时的Header数据</param>
/// <param name="canCancel"></param>
private void savePost(object eventProvider, ref object postUrl, ref object flags, ref object targetFrameName
, ref object postData, ref object headers, ref bool canCancel)
{
bool isCancel = false;
Monitor.Enter(loginLock);
try
{
if (step == transcribeStep.MouseDown)
{
webBrowser.DocumentCompleted -= ready;
SHDocVw.WebBrowser browserActiveX = webBrowser.ActiveXInstance as SHDocVw.WebBrowser;
if (browserActiveX != null) browserActiveX.BeforeNavigate2 -= saveHandler;
byte[] data = postData as byte[];
if (data != null)
{
string values = Encoding.GetEncoding(webBrowser.Document.Encoding).GetString(postData as byte[]);
string formValues = "&sHoWjIm_AutoLogin_FormValues=";
int index = values.IndexOf(formValues);
if (index != -1)
{
formValues = values.Substring(index + formValues.Length);
if ((index = formValues.IndexOf('&')) != -1) formValues = formValues.Substring(0, index);
saveForm(HttpUtility.UrlDecode(formValues));
}
}
try { _savePost(null, postUrl as string, postData as byte[], headers as string); }
catch { }
step = transcribeStep.GetCookie;
webBrowser.DocumentCompleted += saveResponseCookie;
}
}
catch { isCancel = true; }
finally { Monitor.Exit(loginLock); }
if (isCancel) _cancel(true);
}
#endregion
#region 保存登录后的cookie信息
/// <summary>
/// 保存登录后的cookie信息
/// </summary>
private void saveResponseCookie(object sender, WebBrowserDocumentCompletedEventArgs e)
{
bool isCancel = false;
Monitor.Enter(loginLock);
try
{
if (step == transcribeStep.GetCookie
&& String.Compare(webBrowser.Url.ToString(), e.Url.ToString(), true) == 0)
{
webBrowser.DocumentCompleted -= saveResponseCookie;
afterLoginCookie = webBrowser.Document.Cookie;
step = transcribeStep.Completed;
showjim.sys.threading.task.add(onCompleted, loginData, null);
}
}
catch { isCancel = true; }
finally { Monitor.Exit(loginLock); }
if (isCancel) _cancel(true);
}
#endregion
#region 中断网页登录录制
/// <summary>
/// 中断网页登录录制
/// </summary>
/// <param name="_isOnCompleted">是否执行网页登录录制完成后的处理函数</param>
private void _cancel(bool _isOnCompleted)
{
showWebBrowser(false);
SHDocVw.WebBrowser browserActiveX = webBrowser.ActiveXInstance as SHDocVw.WebBrowser;
Monitor.Enter(loginLock);
try
{
switch (step)
{
case transcribeStep.Load:
webBrowser.DocumentCompleted -= ready;
break;
case transcribeStep.Ready:
webBrowser.DocumentCompleted -= ready;
if (browserActiveX != null) browserActiveX.BeforeNavigate2 -= saveHandler;
break;
case transcribeStep.MouseDown:
webBrowser.DocumentCompleted -= ready;
if (browserActiveX != null) browserActiveX.BeforeNavigate2 -= saveHandler;
break;
case transcribeStep.GetCookie:
webBrowser.DocumentCompleted -= saveResponseCookie;
break;
}
if (step != transcribeStep.Completed)
{
step = transcribeStep.Completed;
if (_isOnCompleted) showjim.sys.threading.task.add(onCompleted, null, null);
}
webBrowser.Navigate(showjim.sys.net.webClient.blankUrl);
}
finally { Monitor.Exit(loginLock); }
}
/// <summary>
/// 中断网页登录录制
/// </summary>
public void cancel() { _cancel(false); }
#endregion
}
有了用户操作数据,然后需要有一个自动模拟操作模块 /// <summary>
/// 网页登录模拟
/// </summary>
[System.Security.Permissions.PermissionSet(System.Security.Permissions.SecurityAction.Demand, Name = "FullTrust")]
[System.Runtime.InteropServices.ComVisibleAttribute(true)]
public class webBrowserLoginSimulate : IDisposable
{
#region 网页登录模拟步骤
/// <summary>
/// 网页登录模拟步骤
/// </summary>
private enum simulateStep
{
/// <summary>
/// 已完成
/// </summary>
Completed,
/// <summary>
/// 加载抓取数据
/// </summary>
NextData,
/// <summary>
/// 根据原有cookie下载数据
/// </summary>
DownLoad,
/// <summary>
/// 加载页面
/// </summary>
Load,
/// <summary>
/// 填写表单
/// </summary>
FillForm,
/// <summary>
/// 获取登录cookie
/// </summary>
GetLoginCookie,
/// <summary>
/// 加载抓取页面
/// </summary>
NavigatingCrawl,
/// <summary>
/// 创建TCP监听
/// </summary>
CreateTcpRawSocket,
/// <summary>
/// 获取httponly相关cookie
/// </summary>
GetHttpOnlyCookie,
/// <summary>
/// 获取浏览器数据
/// </summary>
GetWebBrowerData,
/// <summary>
/// 最后下载数据
/// </summary>
LastDownLoad,
}
#endregion
#region 网页登录模拟抓取数据
/// <summary>
/// 网页登录模拟抓取数据
/// </summary>
private class crawlData
{
/// <summary>
/// 抓取页面地址
/// </summary>
public Uri crawlUri;
/// <summary>
/// 网页登录数据
/// </summary>
public webBrowserLoginData.loginData loginData;
/// <summary>
/// 抓取页面数据后的处理委托
/// </summary>
public showjim.sys.run<byte[], webBrowserLoginData.loginData> onCompleted;
/// <summary>
/// 无登录抓取数据
/// </summary>
public byte[] noLoginData;
/// <summary>
/// 无登录页面重定向地址
/// </summary>
public Uri noLoginRedirectUri;
}
#endregion
/// <summary>
/// 默认加载空白页面秒数
/// </summary>
private const int loadBlankSeconds = 2;
/// <summary>
/// 默认填写表单超时秒数
/// </summary>
private const int loadFillFormSeconds = 60;
/// <summary>
/// 默认停止页面抓取秒数
/// </summary>
private const int stopSocketSeconds = 10;
/// <summary>
/// 网页登录录制浏览器
/// </summary>
private WebBrowser webBrowser;
/// <summary>
/// 网页登录模拟步骤
/// </summary>
private simulateStep step;
/// <summary>
/// 最后导航时间
/// </summary>
private DateTime lastNavigatingTime;
/// <summary>
/// 获取httponly相关cookie的TCP监听
/// </summary>
private showjim.sys.net.rawSocket getCookieSocket;
/// <summary>
/// TCP监听IP地址
/// </summary>
private uint getCookieSocketIp;
/// <summary>
/// TCP监听抓取页面域名
/// </summary>
private string downloadDomain;
/// <summary>
/// 网页登录录制浏览器中抓取页面的数据
/// </summary>
private byte[] webBrowserData;
/// <summary>
/// 网页登录模拟访问锁
/// </summary>
private object loginLock = new object();
/// <summary>
/// 网页登录模拟抓取数据队列
/// </summary>
private List<crawlData> crawlQueue = new List<crawlData>();
/// <summary>
/// 网页登录模拟浏览器所在窗体
/// </summary>
private Form webBrowserForm;
/// <summary>
/// 是否创建网页登录模拟浏览器窗体
/// </summary>
private bool isCreateForm;
/// <summary>
/// 是否创建网页登录模拟浏览器
/// </summary>
private bool isCreateWebBrowser;
模拟操作未完