多次使用了百步梯波板糖公众号的查询成绩功能后,心生了一点疑问和想法。
疑问:
1. 公众号是用什么原理实现成绩的查询的?
2. 公众号获得了我们的学号密码后就可以获得信息,但我们用教务处查成绩时候登陆时需要验证码的。
带着这两个疑问,我就想着制作一个登陆某绝望2005并且至少完成成绩查询的功能软件。
启动项目 : 2015年1月18日
用于开发的语言 : C#
在通过一些学习后,我发现使用使用.net框架中的WebBrowser类可以完成诸如网页的加载,button控件的模拟点击,网页填表的功能。
所以我的初步想法是
首先在学生登陆界面自动填表登陆
然后通过模拟点击《成绩查询》
选择《学年》,选择《学期》.再模拟点击《学期查询》
接下来就是使用firebug对某绝望2005的网页进行分析。
发现如果直接用域名 www.xxxx.edu.cn/jw2005 访问的话,会加加载一个
<frame src="http://jw2005.xxxxxxx.com/">的frame框架
通过直接访问 http://jw2005.xxxxxxx.com后,地址直接转向 学校IP /(一段随机码)/ default2.aspx 的界面,是默认的学生登陆界面。
在该网页下对网页进行分析,就可以更加方便的
发现填写“用户名"的text框id为 ”textUserName“
<input name="txtUserName" id="txtUserName" tabindex="1" class="text_nor" type="text">
填写”密码“的text框 id 为 ”TextBox2“
<input name="TextBox2" id="TextBox2" tabindex="2" class="text_nor" type="password">
填写“验证码”的text框的 id 为 "txtSecretCode"
<input name="txtSecretCode" id="txtSecretCode" tabindex="3" class="text_nor" alt="看不清,换一张" title="看不清,换一张" οnfοcus="show(this);" οnkeydοwn="keydown(this);" οnblur="yzblur(this);" style="PADDING-BOTTOM:1px;LINE-HEIGHT:18px;PADDING-LEFT:2px;PADDING-RIGHT:2px;COLOR:#92a4bf;FONT-SIZE:14px;PADDING-TOP:1px" type="text">
“登陆”按钮 id为 “Button1”
<input name="Button1" value="" id="Button1" class="btn_dl" type="submit">
(吐槽一下,上面的命名方式规范的有,不规范的也有。。)
新建一个winForm程序,添加了一个webBrowser控件(name = webBrowser1)
在窗体加载时,使webBrowser1访问某绝望2005
public Form1()
{
InitializeComponent();
//webBrowser1.Hide();
webBrowser1.Navigate("学校教务IP");
}
声明变量
HtmlDocument hdoc;
HtmlElement user, pwd, yzm, login;
在页面加载完成后,,获取各个控件
private void webBrowser1_DocumentCompleted(object sender, WebBrowserDocumentCompletedEventArgs e)
{
hdoc = webBrowser1.Document;
user = hdoc.GetElementById("txtUserName");
pwd = hdoc.GetElementById("Textbox2");
yzm = hdoc.GetElementById("txtSecretCode");
login = hdoc.GetElementById("Button1");
<pre name="code" class="csharp"> user.SetAttribute("value", UserName); // 获取了各个控件后,就可以进行填表了
pwd.SetAttribute("value", Password);
}
那么问题就来了,验证码怎么解决。我一开始想到是把验证码的图片投放到pictureBox控件上,然后让用户自己输入。
然后又百度了一番后,找到了使用mshtml.dll的方法,首先在引用添加mstml,然后用以下代码实现
public static Image GetRegCodePic(WebBrowser wbMail, string ImgName, string Src, string Alt)
{
HTMLDocument doc = (HTMLDocument)wbMail.Document.DomDocument;
HTMLBody body = (HTMLBody)doc.body;
IHTMLControlRange rang = (IHTMLControlRange)body.createControlRange();
IHTMLControlElement Img;
if (ImgName == "") //如果没有图片的名字,通过Src或Alt中的关键字来取
{
int ImgNum = GetPicIndex(wbMail, Src,Alt);
if (ImgNum == -1) return null;
Img = (IHTMLControlElement)wbMail.Document.Images[ImgNum].DomElement;
}
else
Img = (IHTMLControlElement)wbMail.Document.All[ImgName].DomElement;
rang.add(Img);
rang.execCommand("Copy", false, null);
Image RegImg = Clipboard.GetImage();
Clipboard.Clear();
return RegImg;
}
public static int GetPicIndex(WebBrowser wbMail, string Src, string Alt)
{
int imgnum = -1;
for (int i = 0; i < wbMail.Document.Images.Count; i++) //获取所有的Image元素
{
IHTMLImgElement img = (IHTMLImgElement)wbMail.Document.Images[i].DomElement;
if (Alt == "")
{
if (img.src.Contains(Src)) return i;
}
else
{
if (!string.IsNullOrEmpty(img.alt))
{
if (img.alt.Contains(Alt)) return i;
}
}
}
return imgnum;
}
所以在webBrowser1_DocumentCompleted事件中添加代码在picturesBox1上显示验证码图片
pictureBox1.Image = GetRegCodePic(webBrowser1, "icode", "", ""); // icode 是 验证码图片 的 name
添加一个TextBox用于用户输入验证码,和一个登陆的按钮。
private void btn_Login_Click(object sender, EventArgs e)
{
yzm.SetAttribute("value", textBox1.Text); /填写验证码
login.InvokeMember("click"); // 模拟点击登录按钮。
}
至此就大概实现了登陆的功能