爬取研招网招生信息(一)

尝试用软件工程的方法做的一个“项目”,由于我也是考研人,所以想到这个,其实编码难度不大。

可行性分析

由于最近几年考研人数不断攀升,而查找信息是比较令考研学子头疼,但也十分关键的步骤。中国研究生招生信息网(下简称研招网)是获取信息的重要网站,虽然研招网能提供的信息有限,但如果能有一个简单的工具,让广大学子不用打开浏览器,而只需要输入一些信息就可以模拟在研招网查询信息,也能给考研学子提供一些方便。

需求分析

要求一个命令行工具,实现以下功能:输入学科代码、专业名、学校名、是否包含非全日制的信息,自动获取学校、专业、考试科目信息,并能够保存。

设计

总体设计

设计如下模块:命令行界面模块、请求模块和测试模块

在请求模块,设计分别用于获取学校信息、专业信息、考试科目的子模块。获取的学校信息要包含专业信息页面的URL方便下一步请求;同样,获取的专业信息应包含考试科目页面的URL。

命令行界面模块主要负责与用户交互,应能处理各种用户输入。

测试模块负责测试其他模块。

编码完成后,应编译为可执行程序。

详细设计

既然要访问网络,那肯定是用python
工具准备
python环境+第三方PyPI库:urllib3,lxml,pyinstaller
不用bs4是因为浏览器控制台可以直接复制xpath
不用scrapy,aiohttp等高级库/框架是因为没有必要
不用requests是因为要打包成可执行文件,为防体积过大,依赖越少越好
不用自带的urllib是因为难用且不支持长连接。

总体设计的三个模块分别对应main.py,kaoyan.py,test.py
函数定义如下

moudle kaoyan:
HOST=研招网主页
def getSchoolList(subject,location="",school="",stype="",majoring=""):
    '''
    获取学校列表

    Parameters:
    ---------------
    subject:学科类别(代码),必填项\n
    location:地域,默认为空。如果不给定或给定错误省份将在全国范围内搜索\n
    school:学校,默认为空\n
    stype:学习方式,"全日制"("1") or "非全日制"("2"),默认为空,即全部包含\n
    majoring:专业名称,即二级学科名称

    Returns:
    ---------------
    list[list]  包含搜索到的各学校信息的列表\n
    每个学校信息是包括学校名、省份、是否有研究生院、是否为自划线以及详细信息URL的列表
    '''
def getSchoolMajorList(url,get_subj = False,output_fp = None):
    '''
    根据url获取学校某专业信息

    Parameters
    ----------
    url:包含考试科目的url\n
    get_subj:bool  是否包含考试科目\n
    output_fp:输出文件,默认为None

    Raises
    ------
    当URL不符合给定格式时,引发ValueError

    Returns
    -------
    list[list]  get_subj==False时 包含每个专业信息的列表。每个专业信息包括学院、专业名、研究方向、学习方式、招生人数和考试科目的URL。\n
    get_subj==True时,最后一列包含考试科目
    '''
def getExamSubjects(url):
    '''
    根据包含考试科目的url获取考试科目

    Parameters
    ----------
    url:str 包含考试科目的url

    Raises
    ------
    当URL不是包含考试科目的URL时,引发ValueError

    Returns
    -------
    对于一般专业,返回包含下列元素的tuple:\n
    lang:外国语科目
    major1:专业课1科目
    major2:专业课2科目\n
    对于考查管理类联考的专业,返回包含"(199)管理类综合能力"与外国语科目的tuple

    Notes
    -------
    对于某些专业(如教育学、临床医学等),由于很多学校只有一门专业课,故专业课2显示为"无"
    '''
def save(mresult,file=sys.stdout)->None:
    '''将getSchoolMajorList查询到的结果mresult保存到file中。'''
module main:
def query()->tuple:
	'''提示输入的文字'''
def showResult(lst:Iterable)->None:
	'''显示查询结果'''
def _main()->None:
	'''与用户交互'''
module test:
	'''采用单元测试进行测试,在测试阶段再进行详细设计'''

编码

具体思路

打开研招网,记其站点为HOST
找到查询硕士专业目录的网址
进行请求,观察到其请求步骤为:

  1. 在HOST/zsml/zyfx_search.jsp中输入所需信息。
  2. 点击「查询」按钮,向HOST/zsml/queryAction.do发送POST请求,请求数据包括省市代码、学科代码、专业代码、学习方式等。
  3. 跳转到「院校信息页面」。在该页面点击任意一所学校的超链接,向该链接(以HOST/zsml/querySchAction.do?开头)发送GET请求,无请求数据,也可看作请求数据就是URL的?后面那一堆。
  4. 跳转到包含该专业详细信息的页面(称为「专业信息页面」)。在该页面点击任意专业「考试范围」列的「查看」,向对应链接(以HOST/zsml/kskm.jsp?开头)发送GET请求,无请求数据。
  5. 跳转到包含考试科目的页面。(称为「考试科目页面」)

至于页面结构,如何定位到想要的元素等等,直接控制台复制xpath即可,但要注意某些页面元素是用js动态生成的,遇到这种情况要查看网页源代码,确定脚本的行为,从而获取需要的信息。在实践过程中仅发现专业信息页面的招生人数有这种情况。

实际编码中还发现一些问题:

  1. 需要获取省份名称与代码的对应关系。
  2. 学校、考试科目等文字前面会有括号括起来的代码,一般用户也不需要这些。
  3. 多页查询处理。
  4. 非法参数处理。

具体代码见下文

posted @   m0_51303687  阅读(295)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 震惊!C++程序真的从main开始吗?99%的程序员都答错了
· 【硬核科普】Trae如何「偷看」你的代码?零基础破解AI编程运行原理
· 单元测试从入门到精通
· 上周热点回顾(3.3-3.9)
· winform 绘制太阳,地球,月球 运作规律
点击右上角即可分享
微信分享提示