利用Python批量下载必由学答题卡

零、序言

在期末语文考试结束后,班主任老师想要下载一些高分作文的答题卡,但人工操作下载一张张答题卡是一个费时费力还会出现很多失误的工作,所以笔者决定尝试利用Python编写程序解决该问题。

一、分析目标

经过笔者不懈努力(忽悠),成功拿到了班主任老师的必由学账号,简单分析发现获取答题卡的API如下:

http://study2.biyouxue.com/ByxStudy/Common/getCardImg?tId=5e1bd2f5e4b01028aed.....&&sN=2102XXXXXXXXXXX &&qN=22

不难发现:tId为考试编号,sN为必由学学号,qN为题号

二、数据迭代

利用必由学的单科报告,筛选出作文分数较高同学的姓名及必由学学号并保存在Stu_Info.xlsx文件的StuId表中,格式示范如下:

学号 姓名 作文成绩
2102XXXXXXXXXXX 李华 50

迭代StuId表中的每一行,代码如下,注意row的范围是[1,nrows]

import xlrd

main_path = "G:/Byx/"
file_name = main_path + "Stu_Info.xlsx"
file = xlrd.open_workbook(file_name)
sheet = file.sheet_by_name("StuId") # 读取表StuId
nrows = sheet.nrows # 获取表的行数

for row in range(1,nrows):  # 从第二行开始迭代表中的每一行
	stuNo = sheet.cell_value(row,0) # 学号
	stuName = sheet.cell_value(row,1) # 姓名
	stuScore = sheet.cell_value(row,2) # 作文成绩

结合上一步的内容,笔者的代码如下:

import requests
import xlrd

basic_url = "http://study2.biyouxue.com/ByxStudy/Common/getCardImg" # 获取答题卡的API
testId = "5e1bd2f5e4b01028aed....." # 要获取答题卡的考试ID
main_path = "G:/Byx/"
file_name = main_path + "Stu_Info.xlsx"
file = xlrd.open_workbook(file_name)
sheet = file.sheet_by_name("StuId") # 读取表StuId
nrows = sheet.nrows # 获取表的行数

for row in range(1,nrows):  # 迭代表中的每一行
	stuNo = sheet.cell_value(row,0) # 学号
	stuName = sheet.cell_value(row,1) # 姓名
	stuScore = sheet.cell_value(row,2) # 作文成绩
	url = basic_url+"?tId="+testId+"&&sN="+stuNo+"&&qN="+"22"
	response  = requests.get(url = url)

三、身份验证

实际运行后发现,由于必由学的身份验证,我们的程序并不能获取到图片,因此简单地requests.get(url = url)是不行的。
利用浏览器的查看cookie功能可以发现,在登录必由学后会创建如下Cookies:

'JSESSIONID': 'F619303999663FEB0A9EF2180...',
'SERVERID': '10bd6bc8c7172322b77e5212d97...',
'captcha': '""'

而实测发现,用于身份验证的为JSESSIONID,故进行如下修改:

cookies = {
	'JSESSIONID': 'F619303999663FEB0A9EF2180...'
}
headers = {
	'content-type': 'application/json',
	'User-Agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/60.0.3112.113 Safari/537.36'
}
# 省略中间部分内容
	response  = requests.get(url = url, cookies = cookies, headers = headers)

四、下载图片

一个图片是由字节流数据组成,我们可以把图片分层多个字节流数据,加载到内存,然后复制字节流到一个本地路径,最后组合成一张图片…
但是有一个问题:我们使用完stream之后,没有马上关闭,这样会造成内存资源紧张,如果是批量下载很多图片,这个方式是不可取的。
引用自:https://blog.csdn.net/u011541946/article/details/77700074

在参考了其他博主的下载图片方法后,同时考虑到作文高分答题卡的数量及身份验证等问题,笔者使用如下方法:

for row in range(1,nrows):  # 迭代表中的每一行
	# 省略中间部分内容
	response  = requests.get(url = url, cookies = cookies, headers = headers, stream = True)
	img_Name = stuName + '_' + stuScore + '.png'
	with closing(requests.get(url = url, cookies = cookies, headers = headers, stream = True)) as response:
		with open(main_path + img_Name, 'wb') as file:
			for data in response.iter_content(128):
				file.write(data)
	file.close()

五、完整代码

import requests
import xlrd
import time
from io import BytesIO
from contextlib import closing

basic_url = "http://study2.biyouxue.com/ByxStudy/Common/getCardImg" # 获取答题卡的API
testId = "5e1bd2f5e4b01028aed....." # 要获取答题卡的考试ID

cookies = { # 用于身份验证的cookie
	'JSESSIONID': 'F619303999663FEB0A9EF2180...'
}

headers = {
	'content-type': 'application/json',
	'User-Agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/60.0.3112.113 Safari/537.36'
}

main_path = "G:/Byx/"
file_name = main_path + "Stu_Info.xlsx"
file = xlrd.open_workbook(file_name)

sheet = file.sheet_by_name("StuId") # 读取表StuId
nrows = sheet.nrows # 获取表的行数

for row in range(1,nrows):  # 迭代表中的每一行
	stuNo = sheet.cell_value(row,0) # 学号
	stuName = sheet.cell_value(row,1) # 姓名
	stuScore = sheet.cell_value(row,2) # 作文成绩
	url = basic_url+"?tId="+testId+"&&sN="+stuNo+"&&qN="+"22"
	print("Getting card from: %s" % url)
	response  = requests.get(url = url, cookies = cookies, headers = headers, stream = True)
	img_Name = stuName + '_' + stuScore + '.png'
	with closing(requests.get(url = url, cookies = cookies, headers = headers, stream = True)) as response:
		with open(main_path + img_Name, 'wb') as file:
			for data in response.iter_content(128):
				file.write(data)
	file.close()
	print ("Downloaded card of %s , No %s !" % (stuName, stuNo)) # 当前下载的答题卡
	print ("Remaining %d card(s)!" % (nrows - row - 1)) # 剩余答题卡
	time.sleep(1)
发布了1 篇原创文章 · 获赞 1 · 访问量 66

猜你喜欢

转载自blog.csdn.net/weixin_44618885/article/details/104030284