利用python爬取广西科技大学教务管理信息系统班级课表

操作环境

  1. python 3.6.1
  2. pycharm 5.0.3
  3. WampServer 3.0.6
  4. windows 8(64位)

特点

1.中途退出程序或者断网之后重连再次运行不会抓取到重复的课程表
2.使用MySQL数据库(phpmyadmin)储存数据,方便管理课程表

python安装

  • 我的电脑是64位的,所以我下载的是下面的版本
    下载地址
    选择版本以及系统位数下载
  • 安装完之后必须将python安装的路径添加至系统变量中去
    --> 右击我的电脑-->属性-->高级系统设置-->环境变量-->在path后面添加python的安装路径


    设置环境变量

pycharm安装

下载地址

选择版本

  • 社区版是免费使用的

Python插件安装

安装Python 完毕后,需要安装下列插件。

  • Beautiful Soup
  • PyMySQL
    以管理员模式打开cmd命令提示符,执行命令
    pip install beautifulsoup4
    pip install pymysql

WampServer安装

下载地址
根据系统的位数选择相应的进行下载

根据系统位数进行下载

WampServer安装教程

安装启动之后可能会报错:

64位电脑上启动程序出现丢失MSVCR110.dll的解决办法
启动程序报错如下:
无法启动此程序,因为计算机中丢失MSVCR110.dll。尝试重新安装该程序以解决此问题。
应该很容易就搜索到,缺少这样的dll文件,是没有安装Visual C++ Redistributable for Visual Studio 2012的缘故,
但是在安装了
Visual C++ Redistributable for Visual Studio 2012 X64版本后,运行程序依旧报错这个dll文件丢失,问题就在于,64位电脑中,可以运行32位和64位的程序,因而,如果运行的32位的程序,需要32位的
Visual C++ Redistributable for Visual Studio 2012 X86版本的支持,否则会出现上述的错误,因为软件查找的是X86版本的dll文件,而我安装的X64的,当然会发生丢失**
解决方案:如果你是64位的机器,建议安装下列地址上提供的X86和X64版本,两个版本都安装**

安装地址

下载两个版本

至此,应该可以正常启动WampServer程序了。

注意

启动程序请选择google浏览器打开,用其他浏览器可能会报错或者受限制。


启动WampServer

登录

第一次使用密码为空,直接执行即可。

  • 进入到web页面,点击左上角的新建创建数据库文件


    新建数据库
  • 导入数据库文件


    导入数据库文件

环境都准备好了,下面开始进入主题

网页分析

  • 教务管理信息系统课程表链接分析

例如通信141班课程表的链接:http://172.16.129.117/web_jxrw/cx_kb_bjkb_bj.aspx?xsbh=14040201&xq=17-18-1
从链接的尾部*** .aspx?xsbh=14040201&xq=17-18-1 中的问号?可以看出该网页是用GET的方式请求数据的,第一个参数是xsbh = 14040201,第二个参数是xq = 17-18-1,xq明显是学期拼音首字母缩写,而xsbh应该就是班级编号了。所以我们要先获取所有的班级编号和学期数,然后拼接成班级课表链接,进行遍历抓取课程表:http://172.16.129.117/web_jxrw/cx_kb_bjkb_bj.aspx?xsbh=班级编号&xq=学期

分析网页

  • 抓取所有学期网页分析

教务信息系统查询课表页面地址:http://172.16.129.117/web_jxrw/cx_kb_bjxzall.aspx
打开链接后,查看网页源代码,所有学期数都是放在ID为DDxq的select标签下的option标签(如图),

检查

然后出现下图
获取学期信息

因为在前端开发中,id这个属性的值是唯一的,所以使用Beautiful Soup选择此处的代码为soup.find(id=”DDxq”).find_all(“option”)
这就可以用beautifulsoup插件提取所有学期。

  • 抓取所有学期的python代码

semester.py

import urllib
import urllib.request
from bs4 import BeautifulSoup
import pymysql.cursors

connection = pymysql.connect(
    host='localhost',
    user='root',
    password=' ',
    db='python',
    charset="utf8",
    cursorclass=pymysql.cursors.DictCursor)

def sqlLink(semester):
    try:
        with connection.cursor() as cursor:
            sql = "INSERT INTO `semester` (`semester`) VALUES (%s)"
            #插入数据
            cursor.execute(sql, (semester))
            connection.commit() #提交
    finally:
        # connection.close()
        pass
    return

response = urllib.request.urlopen('http://172.16.129.117/web_jxrw/cx_kb_bjxzall.aspx')
if response.code == 200:
    print ("succeed",response.code)
    html = response.read()
    soup = BeautifulSoup(
        html,
        'html.parser',
        from_encoding = 'gb2312')
    arr = soup.find(id="DDxq").find_all("option")
    for x in arr:
            ch = x.get_text()
            print(ch)
            sqlLink(str(ch))
else:
    print ("failed")
  • 抓取所有班级和班级编号

同样查看教务信息系统,分析网页源码按照上面的方法,所有班级都放在id为Cxbj_all1_bjlist1的select标签下(如图),直接用beautifulsoup抓取。


检查
  • 抓取所有班级的班级编号的python代码
    class.py
import urllib
import urllib.request
from bs4 import BeautifulSoup
import pymysql.cursors

#连接数据库
connection = pymysql.connect(
    host='localhost',
    user='root',
    password=' ',
    db='python',
    charset="utf8",
    cursorclass=pymysql.cursors.DictCursor)

def sqlLink(clssName,classCode,grade):
    try:
        with connection.cursor() as cursor:     #创建游标
            sql = "INSERT INTO `class` (`className`,`classCode`,`grade`) VALUES (%s,%s,%s)"
            #插入一条数据库
            cursor.execute(sql, (clssName,classCode,grade))
            #提交
            connection.commit()
    finally:
        # connection.close()
        pass
    return

response = urllib.request.urlopen('http://172.16.129.117/web_jxrw/cx_kb_bjxzall.aspx')
if response.code == 200:
    print ("succeed",response.code)
    html = response.read()
    #创建soup对象
    soup = BeautifulSoup(
        html,
        'html.parser',
        from_encoding = 'gb2312')
    arr = soup.find(id="Cxbj_all1_bjlist1").find_all("option")
    for x in arr:
            ch = x.get_text()   #获取班级名
            classCode = x['value']
            last = x['value'][0]+x['value'][1]
            if last == "98":
                grade = "19"+last
                pass
            else:
                grade = "20"+last
            print(classCode)
            sqlLink(str(ch),classCode,grade)
else:
    print ("failed")
  • 抓取所有班级的课程表

有了班级列表和学期这些数据,我们就可以遍历班级列表和学期列表来拼接成课程表查询链接,提取每个链接中的课程。


检查

同理,在id为GVkb的table标签下,每天的课程都会放在td标签下。
Python代码为soup.find(id=”GVkb”).find_all(“td”)

  • 抓取所有班级课程表的python代码

此处分为两个python文件, 请按照注释命名文件,第一个是schedule.py,第二个是spider.py,要放在同一目录下运行。

1.schedule.py

import urllib
import urllib.request
from bs4 import BeautifulSoup
import pymysql.cursors

def insertTimeTable(classCode,semester):
    connection = pymysql.connect(
        host='localhost',
        user='root',
        password=' ',
        db='python',
        charset="utf8",
        cursorclass=pymysql.cursors.DictCursor)

    response = urllib.request.urlopen('http://172.16.129.117/web_jxrw/cx_kb_bjkb_bj.aspx?xsbh='+classCode+'&xq='+semester)
    if response.code == 200:
        print ("succeed to open the url, code=",response.code)
        html = response.read()
        soup = BeautifulSoup(
            html,
            'html.parser',
            from_encoding = 'gbk')
        arr = soup.find(id="GVkb").find_all("td")
        note = soup.find(id="TextBox1")

        timeTable = []

        for x in arr:
            ch = x.get_text()
            strings = str(ch).replace("\xa0","none") + "\n"
            timeTable.append(strings)
            if len(timeTable) == 8:
                try:
                    with connection.cursor() as cursor:
                        sql = "INSERT INTO `timetable` (`classCode`,`semester`,`section`,`one`,`two`,`three`,`four`,`five`,`six`,`seven`) VALUES (%s,%s,%s,%s,%s,%s,%s,%s,%s,%s)"
                        cursor.execute(sql, (classCode,semester,timeTable[0],timeTable[1],timeTable[2],timeTable[3],timeTable[4],timeTable[5],timeTable[6],timeTable[7]))
                        connection.commit()
                finally:
                    timeTable = []
                    print("insert succeed!")
                pass
        try:
            with connection.cursor() as cursor:
                sql = "INSERT INTO `timetablenote` (`classCode`,`semester`,`note`) VALUES (%s,%s,%s)"
                cursor.execute(sql, (classCode,semester,note.get_text()))
                connection.commit()
        finally:
            print("note insert succeed!")
        pass

    else:
        print("failed to open the url, code=", response.code)
        pass

2.spider.py

import pymysql.cursors
import schedule

connection = pymysql.connect(
    host='localhost',
    user='root',
    password=' ',
    db='python',
    charset="utf8",
    cursorclass=pymysql.cursors.DictCursor)

try:
    ### get all semester
    with connection.cursor() as cursor:
        sql = "SELECT * FROM `semester`"
        cursor.execute(sql)
        resultSemester = cursor.fetchall()
        # for x in resultSemester:
        #     print(x["semester"])
        #     pass
    ### get all classCode
    with connection.cursor() as cursor:
        sql = "SELECT `classCode` FROM `class`"
        cursor.execute(sql)
        resultClassCode = cursor.fetchall()
        # for x in resultClassCode:
        #     print(x["classCode"])
        # pass

finally:
    i = 0
    pass

for x in resultClassCode:
    classCode = x["classCode"]
    # print("classCode = ",classCode)
    for y in resultSemester:
        semester = y["semester"]
        # print("Semester = ",semester)
        gradeClassCode = int(classCode[0]+classCode[1])
        gradeSemester = int(semester[0]+semester[1])
        try:
            with connection.cursor() as cursor:
                sql = "SELECT `classCode`,`semester` FROM `timetable` WHERE classCode='"+classCode+"' AND semester='"+semester+"'"
                cursor.execute(sql)
                resultRepeat = cursor.fetchone()
        finally:
            # connection.close()
            pass
        if (gradeSemester >= gradeClassCode) and (gradeSemester <= gradeClassCode+3):
            if resultRepeat is None:
                arr = [classCode,semester]
                print(arr)
                schedule.insertTimeTable(classCode,semester)
            else:
                print("The timetable had already exist")
            i += 1
            print(i,"Processing...")

python.sql

-- phpMyAdmin SQL Dump
-- version 4.6.4
-- http://www.phpmyadmin.net

SET SQL_MODE = "NO_AUTO_VALUE_ON_ZERO";
SET time_zone = "+00:00";


/*!40101 SET @OLD_CHARACTER_SET_CLIENT=@@CHARACTER_SET_CLIENT */;
/*!40101 SET @OLD_CHARACTER_SET_RESULTS=@@CHARACTER_SET_RESULTS */;
/*!40101 SET @OLD_COLLATION_CONNECTION=@@COLLATION_CONNECTION */;
/*!40101 SET NAMES utf8 */;

--
-- Database: `python`
--

-- --------------------------------------------------------

--
-- 表的结构 `class`
--

CREATE TABLE IF NOT EXISTS `class` (
  ` id` int(11) NOT NULL AUTO_INCREMENT,
  `className` text NOT NULL,
  `classCode` text NOT NULL,
  `grade` int(11) NOT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 AUTO_INCREMENT=1 ;

-- --------------------------------------------------------

--
-- 表的结构 `semester`
--

CREATE TABLE IF NOT EXISTS `semester` (
  `semester` text NOT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

-- --------------------------------------------------------

--
-- 表的结构 `timetable`
--

CREATE TABLE IF NOT EXISTS `timetable` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `classCode` text NOT NULL,
  `semester` text NOT NULL,
  `section` text NOT NULL,
  `one` text NOT NULL,
  `two` text NOT NULL,
  `three` text NOT NULL,
  `four` text NOT NULL,
  `five` text NOT NULL,
  `six` text NOT NULL,
  `seven` text NOT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 AUTO_INCREMENT=1 ;

-- --------------------------------------------------------

--
-- 表的结构 `timetablenote`
--

CREATE TABLE IF NOT EXISTS `timetablenote` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `classCode` text NOT NULL,
  `semester` text NOT NULL,
  `note` text NOT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 AUTO_INCREMENT=1 ;

/*!40101 SET CHARACTER_SET_CLIENT=@OLD_CHARACTER_SET_CLIENT */;
/*!40101 SET CHARACTER_SET_RESULTS=@OLD_CHARACTER_SET_RESULTS */;
/*!40101 SET COLLATION_CONNECTION=@OLD_COLLATION_CONNECTION */;
  • 运行程序进行班级课程表的爬取

爬取的时间可能会有点长,请耐心等待。在爬取过程中可能会由于网络不稳定出现断线情况,出现断线情况后只能进行手动重新运行程序,但是不会出现重复的课程表爬取现象。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 203,271评论 5 476
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,275评论 2 380
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,151评论 0 336
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,550评论 1 273
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,553评论 5 365
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,559评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,924评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,580评论 0 257
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,826评论 1 297
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,578评论 2 320
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,661评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,363评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,940评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,926评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,156评论 1 259
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,872评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,391评论 2 342

推荐阅读更多精彩内容