1.背景
2020年8月26日,孩子在客厅玩耍的时候摔倒右手手肘骨折,到医院检查需要住院手术治疗。骨折部分愈合后,还需要对韧带进行康复治疗。由于家距离医院较远,每天到医院进行康复不太现实,从长远计量,还是停课,全身心在医院进行治疗康复,因此,完全康复前后差不多浪费了近三个月时间。
在住院期间,零星进行了学习,通过部分练习,感觉到孩子掌握的不够扎实,并且,期中考试也没赶上,因此,一直对孩子的掌握程度心里没底。
这次,期末考试是全县统考,试卷批改相对客观,因此,在知道孩子成绩后,虽然略感欣慰,但是,由于学校不公布班级总体成绩,对他掌握程度的总体判断,没有一个定量判断。
为了得到全班的成绩,就现学了如何爬虫获取成绩,基本情况如下:
2.成绩系统分析
成绩采用易查分发布,手机端查询,只要输入孩子姓名即可得到成绩,同时,网上有利用Python语言爬虫成绩的介绍,从而,印证了爬虫获取全班成绩的可行性。
易查分主界面
3.半自动爬虫
利用c#webbrowser来进行爬虫,核心函数有:
- 自动填写并提交
2.读取返回页面数据并分拣页面成绩
3.1自动填写并提交
利用webbrowser控件显示网页内容,页面上姓名输入框和查询按钮两个项目是需要干预操作的接口。webbrowser获取网页内容doc 后,轮询节点内容,将姓名输入框的填写内容进行填写,然后,找到查询按钮的句柄,点击后即可跳转值新的页面。
private void FillData()
{
//jglist = new List<string>();
HtmlElement ClickBtn = null;
HtmlDocument doc = webBrowser1.Document;
for (int i = 0; i < doc.All.Count; i++)
{
if (doc.All[i].Name == "s_xingming")
{
doc.All[i].InnerText = names[Idx]; // 用户名
}
if (doc.All[i].Id == "yiDunSubmitBtn")
{
ClickBtn = doc.All[i];
}
}
ClickBtn.InvokeMember("Click"); // 点击“登录”按钮
}
3.2读取数据
查询结果页面为一个简单的表格,通过相关资料查找,可以利用正则表达式的方法分拣页面表格内容,具体函数如下文,将分拣出来的成绩字符串记录如字符串数组。
查询结果页面示例
private void ReadData()
{
HtmlDocument doc1 = webBrowser1.Document;
HtmlElementCollection ElementCollection = webBrowser1.Document.GetElementsByTagName("Table");
foreach (HtmlElement item in ElementCollection)
{
string ss = item.InnerHtml.ToLower();
string strRegexR = @"(?<=<tr>)([\s\S]*?)(?=</tr>)"; //构造解析表格数据的正则表达式
string strRegexD = @"(?<=<td[^>]*>[\s]*?)([\S]*)(?=[\s]*?</td>)";
Regex regexR = new Regex(strRegexR);
MatchCollection mcR = regexR.Matches(ss); //执行匹配
bool first = true;
foreach (Match mr in mcR)
{
Regex regexD = new Regex(strRegexD);
MatchCollection mcD = regexD.Matches(mr.Groups[0].ToString()); //执行匹配
string Mydata = "";
for (int i = 0; i < mcD.Count; i++)
{
Mydata += mcD[i].Value + " ,";
}
if (Mydata.Trim().Length>0)
{
jglist.Add(Mydata);
jgStr = Mydata;
}
}
}
}
3.3结果
利用上述核心函数和webbrowser控件,编写了提取成绩的小软件。
操作界面
成绩汇总表
4 程序不足
由于时间有限,利用webbrowser控件,数据操作流程为
数据处理流程
需要等待页面加载,因此自动化运行时,常常页面未加载,即进入读取数据函数,尽管利用了webbrowser的DocumentCompleted函数,可能是水平问题,依然无法很好处理加载后读取的问题。
private void webBrowser1_DocumentCompleted(object sender, WebBrowserDocumentCompletedEventArgs e)
{
if (isIniClick)
{
FillData();
isIniClick = false;
isClick = true;
//Thread.Sleep(10000);
}
if (isClick)
{
// ReadData();
isClick = false;
isSucess = true;
}
}
时间有限,就将程序改为半自动方式,反正一个班级学生人数不多,就逐个点击查询,自动填写并转入查询结果界面,界面加载后,点击读取,读取该学生的成绩,如此循环,得到全班成绩。
后续,如果采用webrequest等估计能够实现自动循环查询。
网友评论