查成绩,算分数,每年的综合测评都是个固定的过程,作为软件开发者,这些过程当然可以交给代码去做,通过脚本进行网络请求获取数据,然后直接进行计算得到基础分直接填表就好了,查成绩再手动计算既容易出错也繁琐,所以本篇的内容就是开发一个爬虫脚本取抓取成绩表,至于综合测评计算,这个没什么意义这里就不说了,分数都有了就都够了。

我们的目的就是通过编写脚本,模仿浏览器进行请求获取源码,再进行解析本地化(或者直接计算)

要抓取到数据,其实方案不止一种,这里会介绍两种不同的方案,达到同样的目的:

模仿浏览器进行请求(速度快)

操作浏览器进行请求(速度慢)

先说第一种,这种方案是普遍的爬虫技术,因为爬取的内容不多,对速度要求也不够,所以就是很简单的一个爬虫过程:

分析请求

模仿请求

对于普通的校园网,一般不做流量限制,所以就算请求频繁,也基本不用担心IP被封禁,所以编写爬虫代码可以不用太过担心。先说我所在学校的校园网,是杭州方正软件公司开发的。

① 分析请求

分析请求很简单,就是使用浏览器进行请求,然后分析每个请求所发送和接收的信息,这里最简单应该是使用chrome的开发者模式(F12打开)

输入用户名和密码,勾选已认真阅读,接着点击登陆,这样右边的网络窗口中会检查到所有的网络请求,我们只需要找到对应登陆的一个(这里会带有表单):

这个时候,我们可以通过一些测试工具,尝试进行请求对应的这个地址,并且把表单提交上去试试登陆能否成功,如果成功的话,脚本也就可以模拟这个请求,这里用的是chrome商店的一个工具Postman,用法很简单:

登陆成功之后,我们再进行查询成绩:

这里可以看到这次得到了两个新的请求(上图红框的前两个)

仔细观察会发现,第一个请求头中的Referer指向的是第二个请求的地址,所以可以知道,第二个请求是先于第一个请求发送的。其次,我们发现这个请求中也有表单。

再看第二个请求:

它的Referer指向第三个请求,而这个第三个请求实际上登陆成功之后,就已经存在了,它就是请求到主界面的,而这个请求的类型是Get,所以也表明,第三个请求没有传递任何信息给这个请求。

整理可以知道,流程是这样的:

登陆成功后跳转:http://202.192.72.4/xs_main.aspx?xh=2013034743130

点击查询成绩按钮请求:http://202.192.72.4/xscj_gc.aspx?xh=2013034743130&xm=%B3%C2%D6%BE%B7%AB&gnmkdm=N121605 (Get)

点击查询在校成绩请求:http://202.192.72.4/xscj_gc.aspx?xh=2013034743130&xm=%u9648%u5fd7%u5e06&gnmkdm=N121605 (Post)

所以,我们先来模拟第二个,这个请求是Get类型,所以直接请求即可,但是会发现请求会失败,原因是服务器不能知道我们已经进行登陆了:

所以最先想到的办法是带上第一个请求得到的Cookie,但是也是不行,这个时候要用到上面说的Referer标识,这个标识会告诉服务器请求来源,因为登陆成功会在服务器进行登记,这个标记会让服务器知道请求来源于登陆成功的账号:

此时请求返回正常,我们在源码中可以发现有两个隐藏的标签:

这两个标签传递的,其实是第三个请求的参数,这个时候,模拟第三个请求,并且添加对应的Referer(第二个请求的URL),会发现请求也成功了:

这个请求中的url中的一个参数xm被我更改为1了,原本使用的是一种unicode加密编码,把用户名编码过去了,但是实际上这个参数并没有实际意义,%u的格式会破坏Python程序,所以这里直接改成1了。

② 模仿请求

请求分析完毕,就可以开始写代码了:

用到的包:

1 importrequests, xlwt, os2 from bs4 import BeautifulSoup

登录:

1 deflogin(s, number, password):2 print '正在登录账号:'+number3 url = 'http://202.192.72.4/default_gdsf.aspx'

4 data = {'__EVENTTARGET': 'btnDL',5 'TextBox1': number,6 'TextBox2': password,7 '__VIEWSTATE': '/wEPDwULLTExNzc4NDAyMTBkGAEFHl9fQ29udHJvbHNSZXF1aXJlUG9zdEJhY2tLZXlfXxYBBQVjaGtZRIgvS19wi/UKxQv2qDEuCtWOjJdl',8 'chkYD': 'on',9 '__EVENTVALIDATION': '/wEWCgKFvrvOBQLs0bLrBgLs0fbZDAK/wuqQDgKAqenNDQLN7c0VAuaMg+INAveMotMNAuSStccFAvrX56AClqUwdU9ySl1Lo85TvdUwz0GrJgI='}10 s.post(url, data)11 return s.cookies

登录操作没有给后面的请求传递任何参数,这里的Cookies不是必须的,但是登录是必须的,这样告诉服务器我们后面的请求才是合法的。

点击查询成绩按钮:

1 defget_data_for_grade(s, number, password):2 url = 'http://202.192.72.4/xscj_gc.aspx?xh=' + number + '&xm=%B3%C2%D6%BE%B7%AB&gnmkdm=N121605'

3 referer = 'http://202.192.72.4/xs_main.aspx?xh=' +number4 cookies =login(s, number, password)5 response = s.get(url=url, headers={'Referer': referer}, allow_redirects=False, cookies=cookies)6 source =response.text7 soup = BeautifulSoup(source, 'html.parser')8 view_state = soup.find('input', attrs={'id': '__VIEWSTATE'})['value']9 event_validation = soup.find('input', attrs={'id': '__EVENTVALIDATION'})['value']10 states = {'view_state': view_state, 'event_validation': event_validation, 'cookies': cookies, 'origin': url}11 return states

第五行队请求设置Referer,接着通过BeautifulSoup解析源码得到两个隐藏的标签里面value值,第三个请求要用到。

查询所有成绩请求:

1 defcheck_info(s, number, password):2 url = 'http://202.192.72.4/xscj_gc.aspx?xh=' + number + '&xm=1&gnmkdm=N121605'

3 states =get_data_for_grade(s, number, password)4 print '登录成功,正在拉取成绩'

5 data ={6 '__VIEWSTATE': states['view_state'],7 'ddlXN': '',8 'ddlXQ': '',9 'Button2': '',10 '__EVENTVALIDATION': states['event_validation']11 }12 response = s.post(url, data=data, cookies=states['cookies'], headers={'Referer': states['origin']},13 allow_redirects=False)14 return response.text

得到成绩单源码之后,就可以进行解析了,这里解析存放到xls表格中:

1 defwriteToFile(source):2 print '正在写入文档'

3 wb = xlwt.Workbook(encoding='utf-8', style_compression=0)4 soup = BeautifulSoup(source, "html.parser")5 span = soup.find('span', attrs={'id': 'Label5'})6 sheet = wb.add_sheet('成绩单', cell_overwrite_ok=True)7 table = soup.find(attrs={'id': 'Datagrid1'})8 lines = table.find_all('tr')9 for i inrange(len(lines)):10 tds = lines[i].find_all('td')11 for j inrange(len(tds)):12 sheet.write(i, j, tds[j].text)13 try:14 os.remove(span.text + '.xls')15 except:16 pass

17 wb.save(span.text + '.xls')

最后遍历学号进行爬取,这里只爬取默认账号密码的成绩:

1 for i in range(1, 55):2 num = '2013034743001'

3 s =requests.session()4 try:5 if i <= 9:6 writeToFile(check_info(s, num[:12] + str(i), num[:12] +str(i)))7 else:8 writeToFile(check_info(s, num[:11] + str(i), num[:11] +str(i)))9 except:10 pass

11 s.close()

第二种方案,是通过模拟浏览器来进行登录,点击按钮等操作获取成绩,这里用到的是自动化测试框架Selenium。

这种方案的优点是我们不需要像第一种那样要去分析请求,只需要告诉浏览器要怎么做就行了,但是缺点是速度慢。

1 #-*- coding: utf-8 -*-

2 from selenium importwebdriver3 from selenium.webdriver.common.by importBy4 from selenium.webdriver.support.wait importWebDriverWait5 from selenium.webdriver.common.action_chains importActionChains6 from selenium.webdriver.support importexpected_conditions as EC7 from selenium.common.exceptions importNoSuchElementException8 from selenium.common.exceptions importNoAlertPresentException9 from bs4 importBeautifulSoup10 importxlwt11 importos12

13

14 classScript():15 defsetUp(self):16 self.driver =webdriver.Chrome()17 self.driver.implicitly_wait(10)18 #self.driver.maximize_window()

19 self.base_url = "http://202.192.72.4/"

20 self.verificationErrors =[]21 self.accept_next_alert =True22

23 deftest_jb(self, num):24 driver =self.driver25 driver.get(self.base_url + "/default_gdsf.aspx")26 driver.find_element_by_id("TextBox1").clear()27 driver.find_element_by_id("TextBox1").send_keys(num)28 driver.find_element_by_id("TextBox2").clear()29 driver.find_element_by_id("TextBox2").send_keys(num)30 driver.find_element_by_id("chkYD").click()31 driver.find_element_by_id("btnDL").click()32 WebDriverWait(driver, 5).until(EC.alert_is_present()).accept()33 self.open_and_click_menu(driver)34 retry =035 while retry <= 2:36 try:37 driver.switch_to.frame(driver.find_element_by_id('iframeautoheight'))38 WebDriverWait(driver, 5).until(EC.visibility_of_element_located((By.XPATH, "//input[@id='Button2']")))39 break

40 except:41 print '重新点击按钮'

42 driver.switch_to.parent_frame()43 self.open_and_click_menu(driver)44 retry += 1

45 else:46 print '重试失败'

47

48 source =driver.page_source49 driver.find_element_by_xpath("//input[@id='Button2']").click()50

51 defsource_change(driver):52 if source ==driver.page_source:53 returnFalse54 else:55 returndriver.page_source56

57 self.writeToFile(WebDriverWait(driver, 10).until(source_change))58 driver.quit()59

60 defopen_and_click_menu(self, driver):61 menu1 = WebDriverWait(driver, 5).until(EC.visibility_of_element_located((By.XPATH, "//ul[@class='nav']/li[5]")))62 menu2 = driver.find_element_by_xpath("//ul[@class='nav']/li[5]/ul/li[3]")63 ActionChains(driver).move_to_element(menu1).move_to_element(menu2).click(menu2).perform()64

65 defis_element_present(self, how, what):66 try:67 self.driver.find_element(by=how, value=what)68 exceptNoSuchElementException as e:69 returnFalse70 returnTrue71

72 defis_alert_present(self):73 try:74 self.driver.switch_to_alert()75 exceptNoAlertPresentException as e:76 returnFalse77 returnTrue78

79 defclose_alert_and_get_its_text(self):80 try:81 alert =self.driver.switch_to_alert()82 alert_text =alert.text83 ifself.accept_next_alert:84 alert.accept()85 else:86 alert.dismiss()87 returnalert_text88 finally:89 self.accept_next_alert =True90

91 deftearDown(self):92 self.driver.quit()93 self.assertEqual([], self.verificationErrors)94

95 @staticmethod96 defwriteToFile(source):97 wb = xlwt.Workbook(encoding='utf-8', style_compression=0)98 soup = BeautifulSoup(source, "html.parser")99 span = soup.find('span', attrs={'id': 'Label5'})100 sheet = wb.add_sheet('成绩单', cell_overwrite_ok=True)101 table = soup.find(attrs={'id': 'Datagrid1'})102 lines = table.find_all('tr')103 for i inrange(len(lines)):104 tds = lines[i].find_all('td')105 for j inrange(len(tds)):106 sheet.write(i, j, tds[j].text)107 try:108 os.remove(span.text + '.xls')109 except:110 pass

111 wb.save(span.text + '.xls')112

113

114 if __name__ == "__main__":115 #unittest.main()

116 s =Script()117

118 for i in range(1, 50):119 num = '2013034743101'

120 s.setUp()121 try:122 if i <= 9:123 s.test_jb(num[:12] +str(i))124 else:125 s.test_jb(num[:11] +str(i))126 except:127 pass

这种方法的意义只是熟悉一下自动化测试框架,因为速度实在太慢了,也就不详细介绍了,这里粗略说一下,其实原理就是通过查到网页中对应的控件,进行点击或者悬浮于上面等等的操作,一步一步的到达最后的成绩单,要做的是控制整个流程,明确在什么时候应该停一下等控件出现,什么时候要去点击。

而且到目前为止,这个框架还是有一些Bug的,比如火狐浏览器的驱动无法实现在一个按钮上Hover的操作等等。

python攻击校园网_Python--校园网爬虫记相关推荐

  1. python网络信息提取_python网络爬虫与信息提取I

    一.Requests库的安装 安装Requests非常简单,只需一行代码即可.首先以管理员身份运行cmd,输入如下代码: 1.pip的安装 其实一般安装的python其Script文件包下都会自带有p ...

  2. python绘制糖葫芦_python简单爬虫(一)

    学习python前纠结了下,到底是应该一个个知识点吃透,然后写些小程序.还是应该快速掌握基础语法,快速实践.思考后认为前者这么学习速度真心不高,于是花2天时间看了下python3的语法,虽然很多都不明 ...

  3. python分布式编程_python分布式爬虫中的rules有什么用

    python分布式爬虫中的rules有什么用 发布时间:2020-11-30 14:04:49 来源:亿速云 阅读:100 作者:小新 这篇文章主要介绍python分布式爬虫中的rules有什么用,文 ...

  4. 百家号 python高手养成_python高手养成记04:python的所有数据类型,一篇足矣

    上一篇:python高手养成记03:面向对象是什么?网友:能3天掌握一门语言 题序: 在上一篇中,我们理解了面向对象的思想,只需要大致理解即可,因为后面我们会专门做这一块的培训.在本篇中,小编来讲解p ...

  5. python断点续传下载_Python 3 爬虫|第12章:并发下载大文件 支持断点续传

    1. stream 流式下载大文件 1.1 stream=True 和 iter_content() 我们将继续使用 Python 3 爬虫|第3章:同步阻塞下载 所搭建的测试环境,在 Nginx 默 ...

  6. python古诗默写_Python网络爬虫:爬取古诗文中的某个制定诗句来实现搜索

    Python网络爬虫:爬取古诗文中的某个制定诗句来实现搜索 发布时间:2020-07-20 23:48:19 来源:51CTO 阅读:883 python编译练习,为了将自己学习过的知识用上,自己找了 ...

  7. 爬虫python下载视频_Python视频爬虫实现下载头条视频功能示例

    本文实例讲述了Python视频爬虫实现下载头条视频功能.分享给大家供大家参考,具体如下: 一.需求分析 抓取头条短视频 思路: 分析网页源码,查找解析出视频资源url(查看源代码,搜mp4) 对该ur ...

  8. python天涯帖子_python 网络爬虫(一)爬取天涯论坛评论

    我是一个大二的学生,也是刚接触python,接触了爬虫感觉爬虫很有趣就爬了爬天涯论坛,中途碰到了很多问题,就想把这些问题分享出来, 都是些简单的问题,希望大佬们以宽容的眼光来看一个小菜鸟

  9. python网络信息提取_Python网络爬虫与信息提取入门13

    Part28 1三种信息标记形式的比较 下面我们来比较一下三种信息标记形式. XML是一种用尖括号标签表达信息的一种形式,JSON是用一种有类型的键值对标记信息的表达形式,YAML是用无类型的键值对标 ...

  10. Python课设实验 之 爬虫应用——校园网搜索引擎(使用bs4进行数据分析.)

    题目要求: 第3题  爬虫应用--校园网搜索引擎 本题旨在使用Python建立一个适合校园网使用的Web搜索引擎系统,它能在较短时间内爬取页面信息,具有有效准确的中文分词功能,实现对校园网上新闻信息的 ...

最新文章

  1. 微软职位内部推荐-Senior Software Engineer II-Search
  2. Android 8.0 Oreo 国内可用测试平台上线
  3. 机器学习(MACHINE LEARNING) 【周志华版-”西瓜书“-笔记】 DAY9-聚类
  4. pip install transformers出现拒绝访问
  5. 网页性能优化04-函数节流
  6. 广东工业大学计算机学院研究生招生,蔡瑞初-广东工业大学研究生招生信息网...
  7. G1 解决Evacuation Failure和Humongous Allocation
  8. 使用XFire+Spring构建Web Service(一)——helloWorld篇
  9. 简单的css缩放动画,仿腾讯新闻的分享按钮和美团app底部的图标样式
  10. Apollo自动驾驶入门课程第③讲 — 定位
  11. Chapter1-6_Speech_Recognition(RNN-T Training)
  12. tablespace innodb_index_stats is missing
  13. 面试中的智力题及编程实践(二)
  14. 像素类沙盒游戏还存有哪些致命伤?
  15. php 转换中文乱码,解决php中文乱码转换问题
  16. 利用IDEA模板快速生成swagger注解
  17. 2020-12-11静态路由汇总实验
  18. 超可爱的宝藏网站,看看你在漫画中长什么样
  19. Wordpress最强大的主题-2019最新The7.7主题
  20. 计算机主机前后,电脑cpu后面的字母是什么意思

热门文章

  1. S-PTAM:Stereo Parallel Tracking and Mapping论文笔记
  2. Reed-Solomon纠错码(RS码)(里德-所罗门码)
  3. 2016西安教师职称计算机考试,2016年教师职称计算机考试题库.doc
  4. golang学习之远程木马demo编写
  5. ZIP:ZipEntry
  6. 遥感、GIS、计算机视频教程
  7. VSS的基本使用操作介绍
  8. 参考答案+实验设计与分析(第6版) [Design and analysis of experiments] - 蒙哥马利(Montgomery D.C)
  9. 微服务架构的理论基础 - 康威定律
  10. 微型计算机常常采用三种线结构,2016年河海大学929地理信息系统之地理信息系统概论考研复试题库...