Python爬虫:爬取北京师范大学珠海分校课程表

本篇文章只是记录一下python课的小作业而已没啥技术含量。(顺便练练Markdown语法?)

需要的库:

  • requests:请求网站
  • bs4:用于解析HTML文件
  • PIL:图像处理标准库,看验证码
  • lxml:依旧是一个很好用的解析库
  • io

实现过程:

模拟登陆:

准备工作

  • 打开教务网站,再打开开发者工具,有一个network选项,登陆后能看你的登录操作提交了哪些东西,我们就是要来模拟这个。
    Python爬虫:爬取北京师范大学珠海分校课程表
    登陆之后:一般正方的教务系统都是这个文件
    Python爬虫:爬取北京师范大学珠海分校课程表
    Python爬虫:爬取北京师范大学珠海分校课程表
  • __VIEWSTATE和__EVENTVALIDATION每一次打开登录界面都不同,在模拟登陆之前,我们还得要提前提取这两个信息。
    ‘TextBox1’: 学号
    ‘TextBox2’:密码
    ‘TextBox3’:验证码

session可以保持连接并多次请求
index就是教务网站的 html

session=requests.session()#能够帮我们跨请求保持某些参数,也会在同一个session实例发出的所有请求之间保持cookies。
url="http://es.bnuz.edu.cn/"
login_page=session.get(url,headers=headers)

我们先构造这个字典

datas={  
        'TextBox1':'',  
        'TextBox2':'',  
        'TextBox3':'',  
        'RadioButtonList1':u"学生".encode('gb2312','replace'),  
        'Button4_test': '',  
        '__VIEWSTATE':'',  
        '__EVENTVALIDATION':'',  
        '_VIEWSTATEGENERATOR':'',  
        '__PREVIOUSPAGE':''  
    }  

验证码:

只有学号和密码是不能登录的,我们还要拿到它的验证码。
验证码图片可以通过开发者工具里面找到其src:
http://es.bnuz.edu.cn/CheckCode.aspx
再利用图片标准库在python中打开这个图片

def get_check_code(checkcode,session,headers):
    img = session.get(checkcode, stream=True, headers=headers)
    check_code = int(input("input code:"))
    with open('checkcode.gif', 'wb') as f:
        f.write(img.content)
    image = Image.open('checkcode.gif')
    image.show()
    return check_code

__VIEWSTATE和__EVENTVALIDATION等

通过id来获取
Python爬虫:爬取北京师范大学珠海分校课程表

    soup=bs4.BeautifulSoup(login_page.content,'lxml')
    VIEWSTATE=soup.find('input',id='__VIEWSTATE')['value']
    EVENTVALIDATION=soup.find('input',id='__EVENTVALIDATION')['value']
    VIEWSTATEGENERATOR=soup.find('input',id="__VIEWSTATEGENERATOR")['value']
    PREVIOUSPAGE=soup.find('input',id='__PREVIOUSPAGE')['value']
    check_code_page = 'http://es.bnuz.edu.cn/CheckCode.aspx'
    datas['__VIEWSTATE']=VIEWSTATE
    datas['__EVENTVALIDATION']=EVENTVALIDATION
    datas['TextBox3']=get_check_code(check_code_page,session,headers)
    datas['_VIEWSTATEGENERATOR']=VIEWSTATEGENERATOR
    datas['__PREVIOUSPAGE']=PREVIOUSPAGE

这样我们就完成了提交请求的data的部分

session.post(url,data=datas,headers=headers)

利用post提交后我们就进入到了学生主页

进入课程表

请求到学生的主页之后,我们再用get请求就可以进入到课表界面,不过需要注意的是我们的请求头需要做一些变化。
Referer是你主页的URL

headers = {
        'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/71.0.3578.98 Safari/537.36',
        'Referer':'http://es.bnuz.edu.cn/xs_main.aspx?xh=******',
        'Host': 'es.bnuz.edu.cn'
    }

我们还需要学生课表界面的URL,每个人的课表界面URL是不一样的,获取到的html还需要编码一下。

  url='http://es.bnuz.edu.cn/jwgl/xskbcx.aspx?xh=123456&xm=%E6%A2%81%E5%BF%97%E6%B5%A9&gnmkdm=N121601'
    result = session.get(url,headers=headers)
    con = result.content.decode('utf-8')#con就是课表界面html了

解析课程表

然后就可以对课表界面的html进行解析了,解析的方法有很多,我就不显示了。

代码实现

#!/usr/bin/env python
# -*- coding: UTF-8 -*-
import requests
import bs4
from PIL import Image
import csv
import lxml
import io
import codecs

def login(std_id,passw):
    headers={
    'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/71.0.3578.98 Safari/537.36',
    }
    datas={
        'TextBox1':std_id,
        'TextBox2':passw,
        'TextBox3':'',
        'RadioButtonList1':u"学生".encode('gb2312','replace'),
        'Button4_test': '',
        '__VIEWSTATE':'',
        '__EVENTVALIDATION':'',
        '_VIEWSTATEGENERATOR':'',
        '__PREVIOUSPAGE':''
    }
    session=requests.session()#能够帮我们跨请求保持某些参数,也会在同一个session实例发出的所有请求之间保持cookies。
    url="http://es.bnuz.edu.cn/"
    login_page=session.get(url,headers=headers)
    soup=bs4.BeautifulSoup(login_page.content,'lxml')
    VIEWSTATE=soup.find('input',id='__VIEWSTATE')['value']
    EVENTVALIDATION=soup.find('input',id='__EVENTVALIDATION')['value']
    VIEWSTATEGENERATOR=soup.find('input',id="__VIEWSTATEGENERATOR")['value']
    PREVIOUSPAGE=soup.find('input',id='__PREVIOUSPAGE')['value']
    check_code_page = 'http://es.bnuz.edu.cn/CheckCode.aspx'
    datas['__VIEWSTATE']=VIEWSTATE
    datas['__EVENTVALIDATION']=EVENTVALIDATION
    datas['TextBox3']=get_check_code(check_code_page,session,headers)
    datas['_VIEWSTATEGENERATOR']=VIEWSTATEGENERATOR
    datas['__PREVIOUSPAGE']=PREVIOUSPAGE
    session.post(url,data=datas,headers=headers)
    return session
def get_check_code(checkcode,session,headers):
    img = session.get(checkcode, stream=True, headers=headers)
    with open('checkcode.gif', 'wb') as f:
        f.write(img.content)
    image = Image.open('checkcode.gif')
    image.show()
    check_code = int(input("input code:"))
    return check_code

def into_curriculum(session):
    headers = {
        'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/71.0.3578.98 Safari/537.36',
        'Referer':'http://es.bnuz.edu.cn/xs_main.aspx?xh=123456',
        'Host': 'es.bnuz.edu.cn'
    }
    url='http://es.bnuz.edu.cn/jwgl/xskbcx.aspx?xh=123456&xm=123456&gnmkdm=N121601'
    result = session.get(url,headers=headers)
    con = result.content.decode('utf-8')
    return con
    home.close()

stu_id=123456
passwd=123456
homepage=login(stu_id,passwd)
f=into_curriculum(homepage)
soup=bs4.BeautifulSoup(f,'lxml')
soup=soup.find(id='table1')
soup=soup.findAll('li')
for st in soup:
    print(st.getText())

效果图

原谅我没排版…
Python爬虫:爬取北京师范大学珠海分校课程表

其实还有很多细节我并没有展开来讲啦,比如header和session等等,请自行搜索相关内容吧。

谢谢观看!