[Python]网络爬虫(十):一个爬虫的诞生全过程(以山东大学绩点运算为例)...

2023-10-27

先来说一下我们学校的网站:

http://jwxt.sdu.edu.cn:7777/zhxt_bks/zhxt_bks.html

查询成绩需要登录,然后显示各学科成绩,但是只显示成绩而没有绩点,也就是加权平均分。

显然这样手动计算绩点是一件非常麻烦的事情。所以我们可以用python做一个爬虫来解决这个问题。



1.决战前夜

先来准备一下工具:HttpFox插件。

这是一款http协议分析插件,分析页面请求和响应的时间、内容、以及浏览器用到的COOKIE等。

以我为例,安装在火狐上即可,效果如图:

可以非常直观的查看相应的信息。

点击start是开始检测,点击stop暂停检测,点击clear清除内容。

一般在使用之前,点击stop暂停,然后点击clear清屏,确保看到的是访问当前页面获得的数据。



2.深入敌后

下面就去山东大学的成绩查询网站,看一看在登录的时候,到底发送了那些信息。

先来到登录页面,把httpfox打开,clear之后,点击start开启检测:


输入完了个人信息,确保httpfox处于开启状态,然后点击确定提交信息,实现登录。

这个时候可以看到,httpfox检测到了三条信息:

这时点击stop键,确保捕获到的是访问该页面之后反馈的数据,以便我们做爬虫的时候模拟登陆使用。



3.庖丁解牛

乍一看我们拿到了三个数据,两个是GET的一个是POST的,但是它们到底是什么,应该怎么用,我们还一无所知。

所以,我们需要挨个查看一下捕获到的内容。

先看POST的信息:


既然是POST的信息,我们就直接看PostData即可。

可以看到一共POST两个数据,stuid和pwd。

并且从Type的Redirect to可以看出,POST完毕之后跳转到了bks_login2.loginmessage页面。

由此看出,这个数据是点击确定之后提交的表单数据。

点击cookie标签,看看cookie信息:


没错,收到了一个ACCOUNT的cookie,并且在session结束之后自动销毁。

那么提交之后收到了哪些信息呢?

我们来看看后面的两个GET数据。

先看第一个,我们点击content标签可以查看收到的内容,是不是有一种生吞活剥的快感-。-HTML源码暴露无疑了:


看来这个只是显示页面的html源码而已,点击cookie,查看cookie的相关信息:



啊哈,原来html页面的内容是发送了cookie信息之后才接受到的。

再来看看最后一个接收到的信息:

大致看了一下应该只是一个叫做style.css的css文件,对我们没有太大的作用。




4.冷静应战

既然已经知道了我们向服务器发送了什么数据,也知道了我们接收到了什么数据,基本的流程如下:

  • 首先,我们POST学号和密码--->然后返回cookie的值
  • 然后发送cookie给服务器--->返回页面信息。
  • 获取到成绩页面的数据,用正则表达式将成绩和学分单独取出并计算加权平均数。

OK,看上去好像很简单的样纸。那下面我们就来试试看吧。

但是在实验之前,还有一个问题没有解决,就是POST的数据到底发送到了哪里?

再来看一下当初的页面:

很明显是用一个html框架来实现的,也就是说,我们在地址栏看到的地址并不是右边提交表单的地址。

那么怎样才能获得真正的地址-。-右击查看页面源代码:

嗯没错,那个name="w_right"的就是我们要的登录页面。

网站的原来的地址是:

http://jwxt.sdu.edu.cn:7777/zhxt_bks/zhxt_bks.html

所以,真正的表单提交的地址应该是:

http://jwxt.sdu.edu.cn:7777/zhxt_bks/xk_login.html

输入一看,果不其然:


靠居然是清华大学的选课系统。。。目测是我校懒得做页面了就直接借了。。结果连标题都不改一下。。。

但是这个页面依旧不是我们需要的页面,因为我们的POST数据提交到的页面,应该是表单form的ACTION中提交到的页面。

也就是说,我们需要查看源码,来知道POST数据到底发送到了哪里:



嗯,目测这个才是提交POST数据的地址。

整理到地址栏中,完整的地址应该如下:

http://jwxt.sdu.edu.cn:7777/pls/wwwbks/bks_login2.login

(获取的方式很简单,在火狐浏览器中直接点击那个链接就能看到这个链接的地址了)


5.小试牛刀

接下来的任务就是:用python模拟发送一个POST的数据并取到返回的cookie值。

关于cookie的操作可以看看这篇博文:

http://blog.csdn.net/wxg694175346/article/details/8925978

我们先准备一个POST的数据,再准备一个cookie的接收,然后写出源码如下:

# -*- coding: utf-8 -*-
#---------------------------------------
#   程序:山东大学爬虫
#   版本:0.1
#   作者:why
#   日期:2013-07-12
#   语言:Python 2.7
#   操作:输入学号和密码
#   功能:输出成绩的加权平均值也就是绩点
#---------------------------------------

import urllib  
import urllib2
import cookielib

cookie = cookielib.CookieJar()  
opener = urllib2.build_opener(urllib2.HTTPCookieProcessor(cookie))

#需要POST的数据#
postdata=urllib.urlencode({  
    'stuid':'201100300428',  
    'pwd':'921030'  
})

#自定义一个请求#
req = urllib2.Request(  
    url = 'http://jwxt.sdu.edu.cn:7777/pls/wwwbks/bks_login2.login',  
    data = postdata
)

#访问该链接#
result = opener.open(req)

#打印返回的内容#
print result.read()   

如此这般之后,再看看运行的效果:


ok,如此这般,我们就算模拟登陆成功了。


6.偷天换日

接下来的任务就是用爬虫获取到学生的成绩。

再来看看源网站。

开启HTTPFOX之后,点击查看成绩,发现捕获到了如下的数据:


点击第一个GET的数据,查看内容可以发现Content就是获取到的成绩的内容。


而获取到的页面链接,从页面源代码中右击查看元素,可以看到点击链接之后跳转的页面(火狐浏览器只需要右击,“查看此框架”,即可):


从而可以得到查看成绩的链接如下:

http://jwxt.sdu.edu.cn:7777/pls/wwwbks/bkscjcx.curscopre


7.万事俱备

现在万事俱备啦,所以只需要把链接应用到爬虫里面,看看能否查看到成绩的页面。

从httpfox可以看到,我们发送了一个cookie才能返回成绩的信息,所以我们就用python模拟一个cookie的发送,以此来请求成绩的信息:

# -*- coding: utf-8 -*-
#---------------------------------------
#   程序:山东大学爬虫
#   版本:0.1
#   作者:why
#   日期:2013-07-12
#   语言:Python 2.7
#   操作:输入学号和密码
#   功能:输出成绩的加权平均值也就是绩点
#---------------------------------------

import urllib  
import urllib2
import cookielib

#初始化一个CookieJar来处理Cookie的信息#
cookie = cookielib.CookieJar()

#创建一个新的opener来使用我们的CookieJar#
opener = urllib2.build_opener(urllib2.HTTPCookieProcessor(cookie))

#需要POST的数据#
postdata=urllib.urlencode({  
    'stuid':'201100300428',  
    'pwd':'921030'  
})

#自定义一个请求#
req = urllib2.Request(  
    url = 'http://jwxt.sdu.edu.cn:7777/pls/wwwbks/bks_login2.login',  
    data = postdata
)

#访问该链接#
result = opener.open(req)

#打印返回的内容#
print result.read()

#打印cookie的值
for item in cookie:  
    print 'Cookie:Name = '+item.name  
    print 'Cookie:Value = '+item.value

    
#访问该链接#
result = opener.open('http://jwxt.sdu.edu.cn:7777/pls/wwwbks/bkscjcx.curscopre')

#打印返回的内容#
print result.read()



按下F5运行即可,看看捕获到的数据吧:


既然这样就没有什么问题了吧,用正则表达式将数据稍稍处理一下,取出学分和相应的分数就可以了。



8.手到擒来

这么一大堆html源码显然是不利于我们处理的,下面要用正则表达式来抠出必须的数据。

关于正则表达式的教程可以看看这个博文:

http://blog.csdn.net/wxg694175346/article/details/8929576

我们来看看成绩的源码:



既然如此,用正则表达式就易如反掌了。


我们将代码稍稍整理一下,然后用正则来取出数据:

# -*- coding: utf-8 -*-
#---------------------------------------
#   程序:山东大学爬虫
#   版本:0.1
#   作者:why
#   日期:2013-07-12
#   语言:Python 2.7
#   操作:输入学号和密码
#   功能:输出成绩的加权平均值也就是绩点
#---------------------------------------

import urllib  
import urllib2
import cookielib
import re

class SDU_Spider:  
    # 申明相关的属性  
    def __init__(self):    
        self.loginUrl = 'http://jwxt.sdu.edu.cn:7777/pls/wwwbks/bks_login2.login'   # 登录的url
        self.resultUrl = 'http://jwxt.sdu.edu.cn:7777/pls/wwwbks/bkscjcx.curscopre' # 显示成绩的url
        self.cookieJar = cookielib.CookieJar()                                      # 初始化一个CookieJar来处理Cookie的信息
        self.postdata=urllib.urlencode({'stuid':'201100300428','pwd':'921030'})     # POST的数据
        self.weights = []   #存储权重,也就是学分
        self.points = []    #存储分数,也就是成绩
        self.opener = urllib2.build_opener(urllib2.HTTPCookieProcessor(self.cookieJar))

    def sdu_init(self):
        # 初始化链接并且获取cookie
        myRequest = urllib2.Request(url = self.loginUrl,data = self.postdata)   # 自定义一个请求
        result = self.opener.open(myRequest)            # 访问登录页面,获取到必须的cookie的值
        result = self.opener.open(self.resultUrl)       # 访问成绩页面,获得成绩的数据
        # 打印返回的内容
        # print result.read()
        self.deal_data(result.read().decode('gbk'))
        self.print_data(self.weights);
        self.print_data(self.points);

    # 将内容从页面代码中抠出来  
    def deal_data(self,myPage):  
        myItems = re.findall('<TR>.*?<p.*?<p.*?<p.*?<p.*?<p.*?>(.*?)</p>.*?<p.*?<p.*?>(.*?)</p>.*?</TR>',myPage,re.S)     #获取到学分
        for item in myItems:
            self.weights.append(item[0].encode('gbk'))
            self.points.append(item[1].encode('gbk'))

            
    # 将内容从页面代码中抠出来
    def print_data(self,items):  
        for item in items:  
            print item
            
#调用  
mySpider = SDU_Spider()  
mySpider.sdu_init()  

水平有限,,正则是有点丑,。运行的效果如图:

ok,接下来的只是数据的处理问题了。。




9.凯旋而归

完整的代码如下,至此一个完整的爬虫项目便完工了。

# -*- coding: utf-8 -*-
#---------------------------------------
#   程序:山东大学爬虫
#   版本:0.1
#   作者:why
#   日期:2013-07-12
#   语言:Python 2.7
#   操作:输入学号和密码
#   功能:输出成绩的加权平均值也就是绩点
#---------------------------------------

import urllib  
import urllib2
import cookielib
import re
import string


class SDU_Spider:  
    # 申明相关的属性  
    def __init__(self):    
        self.loginUrl = 'http://jwxt.sdu.edu.cn:7777/pls/wwwbks/bks_login2.login'   # 登录的url
        self.resultUrl = 'http://jwxt.sdu.edu.cn:7777/pls/wwwbks/bkscjcx.curscopre' # 显示成绩的url
        self.cookieJar = cookielib.CookieJar()                                      # 初始化一个CookieJar来处理Cookie的信息
        self.postdata=urllib.urlencode({'stuid':'201100300428','pwd':'921030'})     # POST的数据
        self.weights = []   #存储权重,也就是学分
        self.points = []    #存储分数,也就是成绩
        self.opener = urllib2.build_opener(urllib2.HTTPCookieProcessor(self.cookieJar))

    def sdu_init(self):
        # 初始化链接并且获取cookie
        myRequest = urllib2.Request(url = self.loginUrl,data = self.postdata)   # 自定义一个请求
        result = self.opener.open(myRequest)            # 访问登录页面,获取到必须的cookie的值
        result = self.opener.open(self.resultUrl)       # 访问成绩页面,获得成绩的数据
        # 打印返回的内容
        # print result.read()
        self.deal_data(result.read().decode('gbk'))
        self.calculate_date();

    # 将内容从页面代码中抠出来  
    def deal_data(self,myPage):  
        myItems = re.findall('<TR>.*?<p.*?<p.*?<p.*?<p.*?<p.*?>(.*?)</p>.*?<p.*?<p.*?>(.*?)</p>.*?</TR>',myPage,re.S)     #获取到学分
        for item in myItems:
            self.weights.append(item[0].encode('gbk'))
            self.points.append(item[1].encode('gbk'))

    #计算绩点,如果成绩还没出来,或者成绩是优秀良好,就不运算该成绩
    def calculate_date(self):
        point = 0.0
        weight = 0.0
        for i in range(len(self.points)):
            if(self.points[i].isdigit()):
                point += string.atof(self.points[i])*string.atof(self.weights[i])
                weight += string.atof(self.weights[i])
        print point/weight

            
#调用  
mySpider = SDU_Spider()  
mySpider.sdu_init()  



本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

[Python]网络爬虫(十):一个爬虫的诞生全过程(以山东大学绩点运算为例)... 的相关文章

随机推荐

  • (Jquery功能篇)easy UI 验证功能

    截图展示 源代码展示
  • redis配置篇-03

    redis的配置文件存放位置 windows系统下 redis的默认配置文件放在安装目录的根目录 即redis windows conf linux系统下 redis的默认配置文件存放在安装目录的根目录 即redis conf 该篇以lin
  • 利用register_forward_hook()精确定位到模型某一层的输入和输出

    在论文中偶然读到一些方法会用到模型中间的隐藏层作为分类器 与模型最后一层作为分类器的性能进行对比 故而思考如何能够简便快捷地实现将模型某一层的输出输出拉取出来的方法 发现有现成hook函数可以做到这一点 hook hook就是一个钩子 用来
  • 华为新版模拟器eNSP Lite安装攻略提前解锁,比EVE上手更快

    最近华为发布了新版模拟器eNSP Lite的产品手册 根据产品手册描述 新版模拟器eNSP Lite基于云端发布 所以安装和登录新版模拟器eNSP Lite的方式和目前版本的eNSP有着很大差距 根据产品手册 我整理了新版模拟器eNSP L
  • openGauss学习笔记-12 openGauss 简单数据管理-UPDATE语句

    文章目录 openGauss学习笔记 12 openGauss 简单数据管理 UPDATE语句 12 1 语法格式 12 2 参数说明 12 3 示例 openGauss学习笔记 12 openGauss 简单数据管理 UPDATE语句 修
  • ubuntu彻底卸载ffmpeg

    彻底卸载ffmpeg 查看ffmpeg sudo dpkg l grep ffmpeg 卸载 sudo find grep w ffmpeg sudo xargs rm r f sudo apt get purge remove ffmpe
  • OSI七层模型与TCP\IP协议

    目录 一 分层思想 二 OSI参考模型 三 TCP IP参考模型 四 TCP IP协议簇的组成 五 数据封装与解封装过程 一 分层思想 1 为什么要分层 很多不同的厂家生产各种型号的计算机 它们运行完全不同的操作系统 但 T C P I P
  • 极度简洁Ubuntu/wsl+cuda+pytorch/TensorFlow深度学习开发环境搭建

    安装CUDA wget https developer download nvidia com compute cuda 11 7 0 local installers cuda 11 7 0 515 43 04 linux run sud
  • 使用opencv时,cmake 编译,CMake Error at CMakeLists.txt:15 (find_package): 报错问题解决

    cmake时 报错CMake Error at CMakeLists txt 15 find package By not providing FindOpenCV cmake in CMAKE MODULE PATH this proje
  • electron-release-server服务器搭建遇坑记

    基础配置来自这里 不过需要另外安装一些依赖 以防出现下面的问题 sudo bower install allow root 会安装下载一堆文件 如一些静态文件js css等 npm install g grunt cli npm insta
  • git lfs linux,Git LFS 操作指南

    Gitee gitee com 已支持 Git LFS 功能 目前该功能针对付费企业开放 Git LFS 简介 Git LFS Large File Storage 大文件存储 是 Github 开发的一个 Git 的扩展 用于实现 Git
  • Node.js安装教程及其简介

    目录 Node js简介 Node js安装教程 案例 步骤一 引入 required 模块 步骤二 创建服务器 分析Node js 的 HTTP 服务器 Node js简介 本质 服务端的JS 引入 required 模块 我们可以使用
  • Java中PrintWriter、BufferedWriter以及BufferredReader基本使用详解

    PrintWriter的使用 PrintWriter 是具有自动行刷新的缓冲字符输出流 这是一个高级流 所谓的自动行刷新 意思就是说 在构造函数中指定autoFlush的值为true时 则 println printf 或 format 方
  • 测试用例_场景法

    场景法 一 应用场合 主要用于测试软件的业务流程和业务逻辑 是一种基于软件业务的测试方法 测试人员把自己当成最终用户 尽可能真实的模拟用于在使用该软件时的各种情景 重点模拟两类操作 模拟用户正确的业务操作流程 验证软件的业务功能是否能够正确
  • 智能车摄像头三轮PID参数调节

    代码已上传CSDN 包含摄像头和PID控制 设置了VIP可取这个小门槛 有兴趣可以点击下方链接自取哈 https download csdn net download weixin 53129688 87714428https downlo
  • 3 个技巧教你轻松查看多开模拟器的端口号~

    此文章来源于项目官方公众号 AirtestProject 版权声明 允许转载 但转载必须保留原链接 请勿用作商业或者非法用途 前言 我们都知道 连接模拟器设备的字符串里 需要填上各个模拟器的端口号 比如雷电模拟器的端口号为5554 auto
  • jsp简单页面计数器

    在制作站点计数器时 如果频繁的访问数数库 比如象哪种每增加一人 便写入数据库或文件的作法 当你的站点有很大的访问量时 必然会影响性能 通常的做法有两种 一是启动一个线程定时写入访问量 二是先在内存中保存访问量 只有当访问量达到一定的数量 比
  • 797. 所有可能的路径

    797 所有可能的路径 难度中等154 给你一个有 n 个节点的 有向无环图 DAG 请你找出所有从节点 0 到节点 n 1 的路径并输出 不要求按特定顺序 二维数组的第 i 个数组中的单元都表示有向图中 i 号节点所能到达的下一些节点 空
  • 如何垂直居中一个浮动元素?

    问题网址 http bbs daxiangclass com thread 163 htm 如何垂直居中一个浮动元素 方法一 已经知道元素高宽 子盒子 div1 width 200px height 200px position absol
  • [Python]网络爬虫(十):一个爬虫的诞生全过程(以山东大学绩点运算为例)...

    先来说一下我们学校的网站 http jwxt sdu edu cn 7777 zhxt bks zhxt bks html 查询成绩需要登录 然后显示各学科成绩 但是只显示成绩而没有绩点 也就是加权平均分 显然这样手动计算绩点是一件非常麻烦