从零开始写Python爬虫 --- 爬虫实践:登录正方教务系统

从零开始写Python爬虫 --- 爬虫实践:登录正方教务系统

上次我们通过cookie登陆了 我的钢铁网。但是实际上这种方式并不是通用和安全的。这次我们来通过分析网站post的登录数据来登录现在各个大学都在用的正方教务系统。


目标分析:

先来看一下我们都很讨厌的教务系统:



从图中我们可以大概分析出我么需要填写的字段:

  • 用户名
  • 密码
  • 验证码
  • 身份选择

需要注意的就是验证码

可以知道验证码是以图片的方式浮现在文本框上的,
Python有很多图像识别的第三方库,
但是准确率和使用上都比较麻烦。
这里我选择找到验证码的图片链接,并下载到本地,
通过用户手动输入验证码来完成登录


验证码的抓取:

仔细分析一下网页,
我们可以直接找到验证码其实是一个图片:

<img id="icode" src="CheckCode.aspx" onclick="reloadcode();" alt="看不清,换一张" title="看不清,换一张" alt="" border="0" style="POSITION:absolute;TOP:5px;LEFT:130px" />

分析一下不难得出图片的连接:

http://jw.****.edu.cn/(gxv2le55n4jswm45mkv14o2n)/CheckCode.aspx

通过这个连接我们可以知道教务系统是通过ASP.NET开发的


Post数据的抓取:

我们如何能知道每次我们提交登录按钮之后,
我们都想服务器提交了哪些数据呢?

这又要用到Chrome开发者工具了

这里给一个技巧,我们可以先故意输入一个 错误的值
来追踪一下我们究竟post了哪些值

打开 Chrome开发者工具 --- Networks --- 勾选 Preserve log

输入一些值,点击 登录按钮,

在点开右边的 Headers 拉倒最后的 FromData:

这里就是我们提交数据:


这个字典里,我们很容易可以看到我们需要自己填写的值:

post的数据一般是通过键值对的形式传到服务器的,一般是字典或json格式

  • txtUserName: 用户名
  • TextBox: 密码
  • txtSecretCode: 验证码
  • RadioButtonList1 :选择按钮 学生(这里需要我们手动编码成gbk编码)

但是其他乱七八糟的又是什么?
其中最奇怪的是第一个: ——VIEWSTATE

这一长串随机的值,实际上是正方系统的一个简单的验证手段。
我们在登录页面的原单代码里搜一下这串值:


原来是input栏里的value
找到他的位置之后,
我们就可以很简单的构造出我们需要post的字典了


代码的书写:

由于只是想分享一下登录的过程,
爬虫的部分,我只是抓取了登录人的名字作为验证,
代码也比较简陋,大家看个思路就成:

import requests
import bs4
import os
# 这是Python的一个非常有名的图片库,这里我们用它来显示验证码
from PIL import Image

def get_post_data(url):

    # 首先获取到登录界面的html
    html = requests.get(url
                        )

    soup = bs4.BeautifulSoup(html.text, 'lxml')

    # 找到form的验证参数
    __VIEWSTATE = soup.find('input', attrs={'name': '__VIEWSTATE'})['value']
    

    # 下载验证码图片
    pic = requests.get(
        'http://jw.****.edu.cn/(gxv2le55n4jswm45mkv14o2n)/CheckCode.aspx').content
    with open('ver_pic.png', 'wb') as f:
        f.write(pic)

    # 打开验证码图片
    image = Image.open('{}/ver_pic.png'.format(os.getcwd()))
    image.show()

    # 构造需要post的参数表
    data = {'txtUserName': '',
            'Textbox1': '',
            'TextBox2': '',
            'txtSecretCode': "",
            '__VIEWSTATE': '',
            # 这里我将radio栏--学生 encode成gbk编码,以符合数据的要求
            'RadioButtonList1': '\xd1\xa7\xc9\xfa',
            'Button1': '',
            'lbLanguage': '',
            'hidPdrs': '',
            'hidsc': '', }

    # 构造登录的post参数
    data['__VIEWSTATE'] = __VIEWSTATE
    data['txtSecretCode'] = input('请输入图片中的验证码')
    data['txtUserName'] = input("请输入学号")
    data['TextBox2'] = input("请输入密码")

    return data
# 登录教务系统
def login(url,data):
    # 通过requests库构造一个浏览器session,这能帮我们自动、持久的管理cookies,
    s = requests.session()
    s.post(url, data=data)
    return s
base_url = 'http://jw.****.edu.cn/(gxv2le55n4jswm45mkv14o2n)/default2.aspx'
data = get_post_data(base_url)
print(data)
# 模拟登录教务系统
brow = login(base_url,data)
test = brow.get(
    'http://jw.****.edu.cn/(gxv2le55n4jswm45mkv14o2n)/xs_main.aspx?xh=14200406101')

# 测试看看是否能找到登陆后的信息
soup = bs4.BeautifulSoup(test.text, 'lxml')
try:
    name = soup.find('span', attrs={'id': 'xhxm'}).text
except:
    name = '登录失败 '
print(name)

结果:


每个学校的教务系统多多少少都有点不一样的地方,
所以我就不给出具体的网址了


每天的学习记录都会 同步更新到:
微信公众号: findyourownway
知乎专栏:从零开始写Python爬虫 - 知乎专栏
blog : www.ehcoblog.ml
Github: Ehco1996/Python-crawler

编辑于 2017-06-05

文章被以下专栏收录