玩味小白程序🐒

强智科技·教务网成绩爬取系列文章之爬虫思路

2020-04-05  本文已影响0人  胜言_

我们学校的教务网是强智科技的,平时必须IE才能打开,而我用Chrome,所以我做了这么一个爬虫工具,方便自己查阅教务网成绩,希望对你有帮助~



用到的python库:re、requests


爬虫思路(xxx代表教务网网址,不便传播)

  1. 创建一个Requests会话对象(所有的爬虫步骤都在该会话下进行)。
1s = requests.Session()
  1. get教务网的登陆页面,返回的头部信息中的cookies信息。
1r = s.get(r'http://xxxxxxxxx/', headers=kdjw_hed)
2cookies = r.headers['Set-Cookie'][0:-12]
  1. 根据获取到cookies信息实时获取当前登录页面的验证码图片信息,并把它的二进制文件信息存储为code.jpg。
1r_verifycode = s.get(r'http://xxxxxxxxx/verifycode.servlet', headers=verifycode_hed)
2with open('code.jpg','wb') as f:
3    f.write(r_verifycode.content)
  1. 请求用户输入验证码,然后把所收到的验证码字符串以及用户输入的学号,密码POST到真正的登录的页面,进而实现模拟登陆。
1r_login = s.post(r'http://xxxxxxxxx/Logon.do?method=logon', headers=post_hed, data=login_data)
  1. 模拟登陆后,先用regex匹配所要获取的成绩数据所在页面的页数,然后再向该url提交查询参数(params),例如:'kksj':开课时间;'PageNum':页码,使用for循环,进而获取到每一页的成绩数据。
1regex = re.compile(r'name = "totalPages" value="(.*?)"')
1#示例:某一页
2r_page = s.get(r'http://xxxxxxxxx/xszqcjglAction.do?method=queryxscj', headers=query_hed, params=page_param, timeout=3)

获取到成绩信息的原始数据之后,我们就可以进行数据的清洗和整理了~


该思路的源代码(代码并不能直接运行)

1#import sys  
2#import io  
3import re  
4import requests  
5#from PIL import Image  
6  
7#改变标准输出的默认编码 8#sys.stdout = io.TextIOWrapper(sys.stdout.buffer, encoding='utf8')  
9 
10def get_cookies(): 
11    '从kdjw/的Set-Cookie获取整个会话的cookies' 
12    kdjw_hed = {'Host': 'xxxxxxxxx', 
13        'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/67.0.3396.99 Safari/537.36',} 
14    r = s.get(r'http://xxxxxxxxx/',headers=kdjw_hed, timeout=3) 
15    #print(r.headers) 
16    #获取到cookies 
17    cookies = r.headers['Set-Cookie'][0:-12] 
18    return cookies 
19 
20def get_verifycode(cookies): 
21    '根据所得cookies获取验证码' 
22    verifycode_hed = {'Cookie': cookies, 
23        'Host': 'xxxxxxxxx', 
24        'Referer': 'http://xxxxxxxxx/', 
25        'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/67.0.3396.99 Safari/537.36',} 
26    #验证码获取 
27    r_verifycode = s.get(r'http://xxxxxxxxx/verifycode.servlet', headers=verifycode_hed, timeout=3) 
28 
29    with open('code.jpg','wb') as f: 
30        f.write(r_verifycode.content) 
31    return True 
32 
33#def show_verifycode(): 
34#    '通过Image模块展示验证码图片,并提示用户输入验证码' 
35#    im = Image.open('code.jpg') 
36#    im.show() 
37#    verifycode = input('请输入验证码: ') 
38#    return verifycode 
39 
40def virtual_login(verifycode, cookies, usr, pwd): 
41    '虚拟登陆教务网' 
42    #模拟登陆 
43    login_data = {'useDogCode': '', 
44        'USERNAME': usr, 
45        'PASSWORD': pwd, 
46        'RANDOMCODE': verifycode} 
47    post_hed = {'Cookie': cookies, 
48        'Host': 'xxxxxxxxx', 
49        'Origin': 'http://xxxxxxxxx', 
50        'Referer': 'http://xxxxxxxxx/', 
51        'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/67.0.3396.99 Safari/537.36', 
52    } 
53    r_login = s.post(r'http://xxxxxxxxx/Logon.do?method=logon', headers=post_hed, data=login_data, timeout=3) 
54    #验证登陆 
55    r_verifylogin = s.get(r'http://xxxxxxxxx/framework/main.jsp', headers=post_hed) 
56    regex = re.compile(r'<title>XXXX大学数字化校园平台-XX科技</title>') 
57    verifylogin = regex.search(r_verifylogin.text) 
58    if verifylogin: 
59        return False 
60    else: 
61        return True 
62 
63def search_and_get_grades_html(cookies, kksj): 
64    '模拟登陆之后,打开成绩查询页面获取并返回成绩源数据' 
65    #成绩查询,针对不止一页成绩数据的情况进行优化 
66    form_data = {'kksj': kksj, 'kcxz': '', 'kcmc': '', 'xsfs': 'qbcj', 'ok':'', } 
67    query_hed = {'Cookie': cookies, 
68        'Host': 'xxxxxxxxx', 
69        'Origin': 'http://xxxxxxxxx/', 
70        'Referer': 'http://xxxxxxxxx/jiaowu/cjgl/xszq/query_xscj.jsp', 
71        'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/67.0.3396.99 Safari/537.36',}
72    r_grade = s.post('http://xxxxxxxxx/xszqcjglAction.do?method=queryxscj', headers=query_hed, data=form_data, timeout=3) 
73    #获取总页数 
74    regex = re.compile(r'name = "totalPages" value="(.*?)"') 
75    totalpages = int(regex.findall(r_grade.text)[-1]) 
76    #按页数获取成绩数据 
77    if totalpages == 1: 
78        print('成功获取第1页成绩数据!!! 共1页.',cookies) 
79        return r_grade.text 
80    else: 
81        html_texts = r_grade.text 
82        print('成功获取第1页成绩数据!!! 共%d页.' % totalpages, cookies) 
83        query_hed.update({'Referer': 'http://xxxxxxxxx/xszqcjglAction.do?method=queryxscj'}) 
84        #print(query_hed) 
85        for pagenum in range(2,totalpages+1): 
86            #巧用params 
87            page_param = {'PageNum':pagenum, 'kksj':kksj} 
88            r_page = s.get(r'http://xxxxxxxxx/xszqcjglAction.do?method=queryxscj', headers=query_hed, params=page_param, timeout=3) 
89            html_texts += r_page.text 
90            print('成功获取第%d页成绩数据!!! 共%d页.' % (pagenum, totalpages), kksj, cookies) 
91        return html_texts 
92 
93def get_code_in_file(): 
94    '创建会话,获取cookies,依此获取并保存验证码图片' 
95    global s, cookies_ 
96    s = requests.Session() 
97    #cookies 
98    cookies_ = get_cookies() 
99    #更新验证码code.jpg
100    get_verifycode(cookies_)
101    return cookies_
102
103def main(verifycode_, cookies_, usr_, pwd_, kksj_):
104    '模拟登陆,验证登陆后获取并返回成绩源数据'
105    orignal_html = ''  #初始化变量orignal_html
106    login = virtual_login(verifycode_, cookies_, usr_, pwd_)
107    if login:
108        orignal_html = search_and_get_grades_html(cookies_, kksj_)
109    #print(orignal_html)110    return orignal_html

经过一番手动测试,发现之前我获取到的仅仅是第一页的成绩数据。对于成绩数据大于一页的同学就显示不了了。
现在,我对之前的代码进行了部分精简和修改,爬虫的正确功能已经实现了,此处应有掌声~
但是,在教务网打不开(大部分情况可能是服务器在未通知的情况下进行维护)的时候,成绩数据是无法获取的。(2018.7.13 22:54, Modified)

上一篇 下一篇

猜你喜欢

热点阅读