网页模拟我知道2种
1:通过HttpRequest的Get/Post的提交方式得到页面
2:使用C#webBrowser控件实现页面模拟点击
在页面有加密算法,或者是随机参数不在解决能力范围内时候使用第2种,简单网页建议使用第1种!
webBrowser使用
在Lode事件中
private void Form1_Load(object sender, EventArgs e)
{
webBrowser1.Navigate(“页面URL”);
}
实现webBrowser1显示页面后,完成加载时触发DocumentCompleted
private void webBrowser1_DocumentCompleted(object sender, WebBrowserDocumentCompletedEventArgs e)
{
webBrowser1.Document.GetElementById("标签Id").InnerText = “我需要填写的字符”;//完成登录名自动填写
HtmlDocument doca = this.webBrowser1.Document; //把当前的webBrowser1显示的文档实例化成一个HtmlDocument对象
for (int i = 0; i < doca.All.Count; i++) //循环查找这个对象的每一个元素
{
if (doca.All[i].TagName == "BUTTON") //如果这个元素是A
{
HtmlElement myelement = doca.All[i]; //就把这个元素实例化成一个HtmlElement对象
if (myelement.OuterText == "登 录" && myelement.Id == "J_SubmitStatic") //如果这个元素的文字是“下一页"
{
myelement.InvokeMember("click"); //对这个元素进行点击
break;
}
}
上面的DocumentCompleted事件中通过遍历网页源码中的BUTTON标签找到Id等于“J_SubmitStatic”显示字符为“登 录”的按钮进行点击
这时候页面会自动模拟点击特效,实现页面的跳转。
很多人在这里直接通过webBrowser1.Document获取页面的源码,却发现页面源码一直是登录前的页面源码
我也在这里卡了很长时间,很多聪明的人知道这种情况会有独立的事件可以获取跳转后的代码。通过测试查看在导航到新文档时触发的webBrowser1的Navigated事件使用webBrowser1.Document成功获取到了跳转后的源码。
private void webBrowser1_Navigated(object sender, WebBrowserNavigatedEventArgs e)
{
string yuanma = webBrowser1.Document;//将页面源码保存到string字符串
}
很多人到了这里基本需求都能完成了,毕竟网页的跳转基本都是根据URL的更替实现页面的跳转。
但是问题又来了,很多知名的网页很多超链接都是放在隐藏在JS中,想单纯的通过源码遍历a标签找到并点击页面的a标签却并不能找到。
这时候我们需要知道浏览器中cookies的作用,开发过网页的人都知道,页面登录后页面的传递权限的控制都基于一个cookies。在我们登录的时候相当于得到了一个身份卡在页面的畅通无阻的浏览都是基于这个身份验证。
知道这一点后webBrowser控件会不会记录我们的cookies呢?
下面我们开始测试:
int count = 0;
private void Form1_Load(object sender, EventArgs e)
{
if (count == 0)
{
webBrowser1.Navigate("登录页");
}
else if (count == 1)
{
webBrowser1.Navigate("登录后可以查看的任何一个超链接");
count = 2;
}
}
private void webBrowser1_DocumentCompleted(object sender, WebBrowserDocumentCompletedEventArgs e)
{
if (webBrowser1.ReadyState == WebBrowserReadyState.Complete)//判断是否加载完成
{
webBrowser1.Document.GetElementById("标签Id").InnerText = “我需要填写的字符”;//完成登录名自动填写
HtmlDocument doca = this.webBrowser1.Document; //把当前的webBrowser1显示的文档实例化成一个HtmlDocument对象
for (int i = 0; i < doca.All.Count; i++) //循环查找这个对象的每一个元素
{
if (doca.All[i].TagName == "BUTTON") //如果这个元素是A
{
HtmlElement myelement = doca.All[i]; //就把这个元素实例化成一个HtmlElement对象
if (myelement.OuterText == "登 录" && myelement.Id == "J_SubmitStatic") //如果这个元素的文字是“下一页"
{
myelement.InvokeMember("click"); //对这个元素进行点击
break;
}
}
}
private void webBrowser1_Navigated(object sender, WebBrowserNavigatedEventArgs e)
{
string yuanma = webBrowser1.Document; //将页面源码保存到string字符串
if(yuanma.Contains("登陆成功显示的页面中一个唯一字段")) //判断字符串是否在登录成功的页面源码中 用于确认登录成功
{
count = 1;//登录成功将全局变量变为1
//设置一个计时器隔时间触发,关于计时器的使用不会的百度吧!
System.Timers.Timer timer = new System.Timers.Timer(3000);//实例化Timer类,设置间隔时间为1000毫秒 就是1秒;.
timer.Enabled = true;
timer.Start();
timer.Elapsed += new System.Timers.ElapsedEventHandler(Form1_Load);//触发Load事件
}
}
private void Timer1_Elapsed(object sender, System.Timers.ElapsedEventArgs e)
{
Application.Restart();
}
由于全局变量count值的改变在触发Load事件时候
if (count == 0)
{
webBrowser1.Navigate("登录页");
}
else if (count == 1)
{
webBrowser1.Navigate("登录后可以查看的任何一个超链接");
count = 2;
}
webBrowser控件会加载 webBrowser1.Navigate("登录后可以查看的任何一个超链接"); 的链接。如果cookies存在,则因为拥有权限直接跳转。
测试通过发现webBrowser控件拥有记住cookies的功能,所以这时候我们就可以随便得到页面的源码了。(很多人说得到源码干嘛,因为我做这个的需求就是获得网页信息实时储存查找)
很多人觉得现在这样基本没啥问题了,获取源码的功能已经完成。只要每次在Navigated事件获取源码加个判断就能准确的得到自己想要的源码。我也这么觉得但是事情总会有例外,想某些有名的网页他的页面带有静态刷新效果URL不变实现跳转,具体的情况我也不是很清楚但是就是在之前突然我想获取源码发现获取不了了,通过断点调试发现获取的源码不完整,无法找到自己要的信息。
Navigated在导航到新文档时触发所以我个人觉得有可能是没达到触发条件 或者是时间没有弄好导致提前运行所以获取源码不完整,但是怎么改都改不到自己想要的效果。最后我突然一想DocumentCompleted事件中我们获取的源码一直是webBrowser1.Navigate(“”)所包含的链接,我通过触发load事件改变webBrowser1.Navigate("")的URL在加载完毕后查看此URL的源码是不是就能获取到。
通过count的改变Time触发加上判断发现可以实现,基本要求已经满足!
private void webBrowser1_DocumentCompleted(object sender, WebBrowserDocumentCompletedEventArgs e)
{
if (webBrowser1.ReadyState == WebBrowserReadyState.Complete)
{
Encoding encoding = Encoding.GetEncoding(webBrowser1.Document.Encoding);
StreamReader stream = new StreamReader(webBrowser1.DocumentStream, encoding);
string ss = stream.ReadToEnd();
if (ss.Contains("J_Submit"))
{
webBrowser1.ScriptErrorsSuppressed = true;
webBrowser1.Document.GetElementById("TPL_username_1").InnerText = "账号";
webBrowser1.Document.GetElementById("TPL_password_1").Focus();
webBrowser1.Document.GetElementById("TPL_password_1").InnerText = "密码"
HtmlDocument doca = this.webBrowser1.Document; //把当前的webBrowser1显示的文档实例化成一个HtmlDocument对象
for (int i = 0; i < doca.All.Count; i++) //循环查找这个对象的每一个元素
{
if (doca.All[i].TagName == "BUTTON") //如果这个元素是A
{
HtmlElement myelement = doca.All[i]; //就把这个元素实例化成一个HtmlElement对象
if (myelement.OuterText == "登 录" && myelement.Id == "J_SubmitStatic") //如果这个元素的文字是“下一页"
{
myelement.InvokeMember("click"); //对这个元素进行点击
break;
}
}
else if (ss.Contains("订单信息"))
{
ss = ss.Split(new string[] { "包含字段" }, StringSplitOptions.None)[1].Split(new string[] { "包含字段" }, StringSplitOptions.None)[0];//对页面进行截取,内容过多
ss.Replace("\t", "\n");
StreamWriter sw = new StreamWriter("a.txt", true, System.Text.Encoding.Unicode);
sw.WriteLine(DateTime.Now + ":");
sw.WriteLine(ss);
sw.WriteLine("------------------------------------------------------------------------------------------------------------------------");
sw.Close();
}
}
}