西电教务处爬虫系统

西电教务处爬虫系统
应该是爬虫的最后一个项目了~
后续会多学习Java的相关知识~

抓包工具Fiddler

内容参考自Fiddler

Fiddler 是以代理web服务器的形式工作的,它使用代理地址:127.0.0.1,端口:8888。

当Fiddler退出的时候它会自动注销, 这样就不会影响别的程序。不过如果Fiddler非正常退出,这时候因为Fiddler没有自动注销,会造成网页无法访问。 解决的办法是重新启动下Fiddler。

个人理解:fiddler是一个抓包工具,当浏览器访问服务器会形成一个请求,此时,fiddler就处于请求之间,当浏览器发送请求,会先经过fiddler,然后在到服务器;当服务器有返回数据给浏览器显示时,也会先经过fiddler,然后数据才到浏览器中显示,这样一个过程,fiddler就抓取到了请求和响应的整个过程。

Fiddler抓包解析

使用fiddler抓包后,会出现如下会话框:

抓包工具面板功能

1
2
3
4
5
6
7
8
9
# :HTTP Request的顺序,从1开始,按照页面加载请求的顺序递增。
Result : HTTP响应的状态 Protocol:请求使用的协议(如HTTP/HTTPS)
HOST:请求地址的域名 URL:请求的服务器路径和文件名,也包含GET参数
BODY:请求的大小,以byte为单位
Content-Type:请求响应的类型
Caching:请求的缓存过期时间或缓存控制header的值
Process:发出此请求的Windows进程及进程ID
Comments :用户通过脚本或者菜单给此session增加的备注
custom:用户可以通过脚本设置的自定义值

fiddler右边面板介绍

Statistics页签

通过该页签, 用户可以通过选择多个会话来得来这几个会话的总的信息统计,比如多个请求和传输的字节数。选择第一个请求和最后一个请求, 可获得整个页面加载所消耗的总体时间。从条形图表中还可以分别出哪些请求耗时最多, 从而对页面的访问进行访问速度优化。

inspectors页签

它提供headers、textview、hexview,Raw等多种方式查看单条http请求的请求报文的信息,它分为上下两部分:上部分为HTTP Request(请求)展示,下部分为HTTPResponse(响应)展示。

AutoResponse页签

Fiddler最实用的功能, 它可以抓取在线页面保存到本地进行调试, 大大减少了在线调试的困难, 可以让我们修改服务器端返回的数据, 例如让返回都是HTTP404或者读取本地文件作为返回内容。

composer页签

支持手动构建和发送HTTP, HTTPS和FTP请求, 我们还可以从web session列表中拖曳session, 把它放到composer选项卡中, 当我们点击Execute按钮, 把请求发送到服务器端。

log页签
打印日志

Filters页签

过滤器可以对左侧的数据流列表进行过滤, 我们可以标记、 修改或隐藏某些特征的数据流。

Timeline页签

时间轴,也称为Fiddler的瀑布图,展示网络请求时间的功能。 每个网络请求都会经历域名解析、建立连接、发送请求、接受数据等阶段。把多个请求以时间作为 X 轴, 用图表的形式展现出来, 就形成了瀑布图。 在左侧会话窗口点击一个或多个(同时按下 Ctrl 键),Timeline 便会显示指定内容从服务端传输到客户端的时间。

爬取教务处学生信息student.py

requests的基本用法

requests的高级特性

登陆页面的url

1
2
3
4
5
6
7
8
9
10
class XDspiderStudent:
def __init__(self, auth_url=None, log_url=None):
if not auth_url:
# 登录界面 post
self.auth_url = "http://ids.xidian.edu.cn/authserver/login?service=http%3A%2F%2Fjwxt.xidian.edu.cn%2Fcaslogin.jsp"
self.log_url = "http://jwxt.xidian.edu.cn/caslogin.jsp"
else:
self.auth_url = auth_url
self.log_url = log_url
self.session = requests.Session()

其中,def __init__定义类的时候,若是添加init方法,那么在创建类的实例的时候,实例会自动调用这个方法,一般用来对实例的属性进行初使化。

self.auth_url是指教务处的登陆页面;

self.log_url是指登陆进去之后的页面。

注:不可以直接将登陆进去之后页面的URL复制过来,因为会自动跳转到登录页。

这一部分内容完成的就是简单的准备工作。

模拟登陆

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
def login(self, id='', password=''):
r = self.session.get(self.auth_url)
data = r.text
bsObj = BeautifulSoup(data, "html.parser")
# 登录所需信息
lt_value = bsObj.find(attrs={"name": "lt"})['value']
exe_value = bsObj.find(attrs={"name": "execution"})['value']
params = {'username': id, 'password': password,
"submit": "", "lt": lt_value, "execution": exe_value,
"_eventId": "submit", "rmShown": '1'}
# 模拟登录报头
headers = {'User-Agent': "Mozilla/5.0 (Windows NT 10.0; WOW64; rv:44.0) Gecko/20100101 Firefox/44.0",
'Accept': "text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8",
"Accept-Language": "zh-CN,zh;q=0.8,en-US;q=0.5,en;q=0.3",
"Accept-Encoding": "gzip, deflate",
"Referer": "http://ids.xidian.edu.cn/authserver/login?service=http%3A%2F%2Fjwxt.xidian.edu.cn%2Fcaslogin.jsp",
"Content-Type": "application/x-www-form-urlencoded"}
s = self.session.post(self.auth_url, data=params, headers=headers)
s = self.session.get(self.log_url)
self.session.get()

该程序中,id是指学生的学号,password是指密码,r = self.session.get(self.auth_url) 访问登陆页面并返回所有的信息。

在我的pycharm中我打印了r的值,返回的是

1
r:<Response [200]>

返回的是网页的状态码,HTTP状态码表示HTTP协议所返回的响应状态。

HTTP状态码有5种,所有状态码的第一个数字代表了响应的5种状态之一:(1)消息:1XX;(2)成功:2XX;(3)重定向:3XX;(4)请求错误:4XX;(5)服务器错误:5XX.

目前常用的就两种:

(1)200:请求成功,请求所希望的响应头或者数据体随此响应返回。

(2)404:Not Found,请求失败,表示请求的资源未被在服务器上发现。整个状态可能是暂时的,也可能是永久的。所以,要做好该状态下的处理。

requests.session.get()

任何时候进行了类似 requests.get()的调用,你都在做两件主要的事情。

其一,你在构建一个 Request 对象,该对象将被发送到某个服务器请求或查询一些资源。

其二,一旦 requests 得到一个从服务器返回的响应就会产生一个 Response 对象。该响应对象包含服务器返回的所有信息,也包含你原来创建的 Request 对象。

如下是一个简单的请求,从 Wikipedia 的服务器得到一些非常重要的信息:

1
r = requests.get('http://en.wikipedia.org/wiki/Monty_Python')
r.text()

python requests的content和text方法的区别

r.text返回的是Unicode型的数据。
r.content返回的是bytes型也就是二进制的数据。

如果你想取文本,可以通过r.text。
如果想取图片,文件,则可以通过r.content。

登陆所需信息

bsObj中打印出来的就是登陆页面的html代码,部分代码如下:

1
2
3
4
<input type="hidden" name="lt" value="LT-703494-JsNeSdd0HmvPjCaGgxJZeBbqmtmQzt1544973307956-zozW-cas" />
<input type="hidden" name="execution" value="e1s1" />
<input type="hidden" name="_eventId" value="submit" />
<input type="hidden" name="rmShown" value="1">

params中存放我们登陆所需的信息。

模拟登陆报头

hearders中的内容是在Fiddler中获得的,其内容是试出来的。

保存为CSV文件

CSV模块的使用

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
def Store(self):
grade_page = self.session.get(
"http://yjsxt.xidian.edu.cn/student/index.jsp")
bsObj = BeautifulSoup(grade_page.text, "html.parser")

table = bsObj.findAll("table", {"class": "tab"})[0]
rows = table.findAll("tr")

csvFile = open('./student.csv', 'w', newline='', encoding='utf-8')
writer = csv.writer(csvFile)
writer.writerow(('姓名', '学号', '培养单位', '入学年月', '录取方式',
'专业', '研究方向', '导师', '已完成总学分', '学位课加权平均分'))
csvRow = []

#
try:
for row in rows:
for cell in row.findAll('td'):
csvRow.append(cell.get_text().strip().rstrip('给导师发消息'))
writer.writerow(csvRow)
finally:
csvFile.close()

"http://yjsxt.xidian.edu.cn/student/index.jsp"这个是学生信息页面的URL;
后续的处理就是HTML代码处理,提取出所需的信息。

CSV (Comma Separated Values),即逗号分隔值(也称字符分隔值,因为分隔符可以不是逗号),是一种常用的文本
格式,用以存储表格数据,包括数字或者字符。

‘w’表示写模式。

首先open()函数打开当前路径下的名字为’./student.csv’的文件,如果不存在这个文件,则创建它,返回csvFile文件对象。

csv.writer(csvFile)返回writer对象writer。

writerow()方法是一行一行写入,writerows方法是一次写入多行。

注意:如果文件’./student.csv’事先存在,调用writer函数会先清空原文件中的文本,再执行writerow/writerows方法。