chapter11-实战成绩通知短信系统(上)

恭喜各位同学!当你看到这篇文章的时候,意味着你已经从刚开始的“一无所知”,变成了现在的“爬虫新手”!在之前的文章中,我们从最基础的知识点讲起,一步一步的学习了怎么使用Python爬取我们想要获取的信息,在这期间,我们也穿插着学习了HTML、Linux、Ajax等技术。
从本章开始,我们将开发我们最后的实践程序——成绩短信通知服务。相对应的,各位同学可以在本课程的Github页面上获取到对应的代码。
注意!因为每个院校的教务系统并不是统一的,本门课程只能选择最广泛使用的某方教务系统,因此可能并不能适配你所在的学校。但是,技术是相同的。相信我,跟着我学习完这两章的课程后,你一定会庆幸你学校的教务系统不会是教程中的系统——事实上,某方的反爬虫技术和代码格式让我在开发的过程中苦不堪言,甚至一度想放弃。庆幸的是,通过不懈的努力,这两篇文章终于能够和之前计划的一样,展现在你们的眼前。废话不多说,让我们直接开始!

登录系统

首先我们需要分析登录系统所要传递的参数,如下图所示,我们在的登录的时候,需要输入的参数有:用户名、密码、验证码以及选择学生
chapter11-实战成绩通知短信系统(上)_第1张图片

但是,事实的确如此吗?很显然,是错误的!我们在上一章节已经讲过:除了上述我们需要填写的显性内容外,我们还需要传递一个证明自己身份的_VIEWSTATE。那么,什么是_VIEWSTATE呢?

_VIEWSTATE是ASP.NET的一个控件。如果在客户端和服务器段保持往返的状态,在.net中通过加入一个隐藏控件_ViewState来实现的,这些状态的保持不需要程序员来控制,节省了程序员的精力。

那么, _VIEWSTATE参数究竟在哪里能够发现呢?很简单,就在网页的源代码中!
在这里插入图片描述

让我们把它解析出来:

import requests
from bs4 import BeautifulSoup
url = "target_url"
rensponse = requests.get(url)
soup = BeautifulSoup(rensponse.text,'lmxl')
_VIEWSTATE = soup.find('input', attrs={'name': '__VIEWSTATE'})['value']

通过使用上个章节介绍的fiddler4 ,我们可以确定登录系统需要传递以下的参数:

  • _VIEWSTATE:.Net框架用来标记用户身份的控件

  • TextBox1:学号参数

  • TextBox2:密码参数

  • TextBox3:验证码

  • RadioButtonList1:学生标记

  • Button1:空值

  • lbLanguage:空值

    事实上,某方教务系统存在不通过验证码即可登录的界面,我在调试的过程中,也一直在使用该页面。但是为了让开发具有普遍性,因此本门默认使用了带有验证码的登录网页。

正如我在上面提到的那样,因为验证码是需要人工输入的,因此在开发的过程中,我们首先将网页中的验证码图片下载到本机,然后采用人工输入的方式,保证准确性。
注意:后续将提供基于机器学习的验证码识别模型,减少人工输入步骤
so,登录所需要的参数都明白了,让我们直接开发吧!

import requests
from bs4 import BeautifulSoup
username='你的用户名'
password='你的密码'
url = 'targeturl'
HEA = {'User-Agent': 'Mozilla/5.0 (Windows NT 6.3; WOW64) AppleWebKit/'
                     '537.36 (KHTML, like Gecko) Chrome/57.0.2987.110 Safari/537.36',
       }

response = requests.get(url,HEA)
if response.status_code=='OK':
    soup = BeautifulSoup(response.text,'lxml')
else:
    hash_url = response.headers['Content-Type']
    url = 'targeturl'
    response = requests.get(url,HEA)
    soup = BeautifulSoup(response.text, 'lxml')
viewState = soup.find('input', attrs={'name': '__VIEWSTATE'})['value']
RadioButtonList1 = u"学生".encode('gb2312','replace')
imgUrl = "targeturl"
imgresponse = s.get(imgUrl, stream=True)
image = imgresponse.content
DstDir = os.getcwd()+"\\"
print("保存验证码到:"+DstDir+"code.jpg"+"\n")
try:
    with open(DstDir+"code.jpg" ,"wb") as jpg:
        jpg.write(image)
except IOError:
    print("IO Error\n")
finally:
    jpg.close
#手动输入验证码
code =input("验证码是:")
data = {
    '__VIEWSTATE':viewState,
    'TextBox1':username,
    'TextBox2':password'

    'RadioButtonList1':RadioButtonList1,
    'Button1':''
}
web_data = requests.post(url=url,data=data,headers=HEA)
print(web_data.text)

运行代码,首先输入我们下载到本地的验证码,然后回车,验证是否登录系统:
chapter11-实战成绩通知短信系统(上)_第2张图片

Bingo!我们成功进入到了教务系统中!
####分析成绩页面
让我们分析一下成绩的URL:

在成绩的URL中,我们需要注意以下几个参数:

  • xh:学生用户名

  • xm:学生姓名的URL编码
    其中xm是通过对学生姓名进行URL编码后得到的字符串。你可以在这个网址验证编码前的信息。
    举个例子,有个男生,名字叫“小强”,我们使用URL编码工具对其进行编码,其对应编码后的字符串为%e5%b0%8f%e5%bc%ba
    解释完参数的含义,让我们选取2016-2017年度第二学期的成绩,使用fiddler4 获取服务器的数据传输详情:
    chapter11-实战成绩通知短信系统(上)_第3张图片

    同样的,我们还是需要分析一下传输的参数:

  • _VIEWSTATE:.Net框架用来标记用户身份的控件

  • _VIEWSTATEGENERATOR:默认即可

  • ddlXN:选择学年

  • ddlXQ:选择的学期

  • Button1:空置
    其中_VIEWSTATE也是可以从网页中获取到的,ddlXNddlXQ是我们选择的学年和学期。
    因为某方的验证手段,我们必须模拟浏览器header,同时加上Referer参数,Referer参数就是我们所在的成绩页面的URL
    让我们开始写代码:

    chengji_page = 'http://xxxx.xxxx.edu.cn/xscj_gc.aspx?xh=xxxxxxxx&xm=%e5%b0%8f%e5%bc%ba&gnmkdm=N121605'
    header = {
      'Referer':''http://xxxx.xxxx.edu.cn/xscj_gc.aspx?xh=xxxxxxxx&xm=%e5%b0%8f%e5%bc%ba&gnmkdm=N121605',
      'User-Agent':'Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/49.0.2623.110 Safari/537.36'
    }
    response = s.get(chengji_page,headers=header)
    __VIEWSTATE= get_view(response)
    data1 = {
              "__VIEWSTATE":__VIEWSTATE,
              "ddlXN":"2016-2017",
              "ddlXQ":"2",
              "Button1":""
    }
    chengji = s.post(chengji_page,data=data1)
    print(chengji.text)
    

    让我们运行该段代码:
    chapter11-实战成绩通知短信系统(上)_第4张图片

    一切显示正常!我们已经获取到了所对应的成绩!接下来,我们需要解析网页,并且将成绩存入数据库中,同时拼接好之前的接口。虽然步骤很多,但是都是我们之前学到的内容,因此,让我们下章将成绩短息通知服务正式完成吧!

总结
  1. 本章完成了成绩短息通知服务的登录获取成绩步骤,这两个步骤是我们开发中最重要的过程,因此同学们有不理解或者不明白的地方,一定要在讨论区发表自己的看法!
  2. 事实上,某方的教务系统代码杂乱无章,或者是有意为之。因此接下来的网页解析,也希望大家能够认真学习;
  3. 在编写课程中,我尝试了使用机器学习去识别验证码,但是准确率只有70%左右,成熟度不够,因此只能使用保守的人工识别验证码的方式保证系统登录正常。在课程的后续过程,甚至是课程结束后,我都会及时更新相关的代码,同时完善验证码的自动识别服务,也希望大家在学习课程后,仍然多多关注本门课程的Github页面,star一下该项目。

你可能感兴趣的:(Python,爬虫从入门到精通,python,爬虫,后端,beautifulsoup,实战)