爬取学校教务处网站,提取并保存信息

最近开始用记录学习过程的点滴。等以后自己学会建博客再移到博客上去吧~

工具:
python3.6.3
requests
BeautifulSoup
xlwt

爬取学校教务处
学了python基础语法,requests和beautsoup,没有练手过,遂到教务处一展拳脚。我学校的教务处登录比较简单,没有验证码,然而我还是不会用post。。。。。

1:构造请求
这里需要伪造一下浏览器:
这里尽显我爬虫渣本色,直接在谷歌浏览器里开发者工具中复制的header

header = {"User-Agent": "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/62.0.3202.94 Safari/537.36"}

此外,登录需要密码账号,我试图用requests的post方法,构建账号密码信息,然而一知半解,在此记录过程,希望有高手解答:

a.打开登录页面-F12-Network抓包,如图:


爬取学校教务处网站,提取并保存信息_第1张图片
image.png

b. 抓包
抓包还看了不少博客,学的三脚猫的功夫:先故意输错密码试试看


image.png

可以看到network中抓取到数据流,点开Form Data, userName和pwd应该就是账号和密码,但是pwd后面这串是什么鬼啊???加密???还有这个sign后面那串数字,我也看不懂,所以post方法暂时行不通,可以留着以后慢慢研究,或者有大神解释解释那是极好的。

穷则思变,变则通达,post不行,我就不学了吗?那肯定不会。在网上看到了另外一招,对新手及其友好的,利用cookies进行登录。

a. 输入账号密码,登录教务处页面,还是打开网络监听F12-Network,点击第一个选项,它是此页中第一个数据流(或者其他叫法,我极其不专业。。。),在右侧找到cookies,如下图


爬取学校教务处网站,提取并保存信息_第2张图片
image.png

关于cookies的原理我也不懂,看文章说是用户与服务器之间的一种凭证,应该就是短时间生成的一种凭证,只要这个凭证有效,那么用户就可以不用登陆就可以访问服务器上面的数据。看它这么乱,应该是用方法加密了,暂且就这么理解吧。

b. 复制这段cookies,我们就可以制作cookies了。使用如下代码:

cookies = {}
raw_cookies = "ASP.NET_SessionId=2gq0mryer************; UserTokeID=f716cffe-************-a84d-**********c"
for line in raw_cookies.split(';'): #用';'对字符串分割
        key, value = line.split('=', 1)
        cookies[key] = value

这个方法我是网上学到的,不过它的作用其实就是将原生的cookies构造成以键值对形式的字典,所以你也可以直接这样:

cookies = {'ASP.NET_SessionId': '2gq0mryer************', 'UserTokeID': 'f716cffe-************-a84d-**********c'}

这样手动将复制下来的raw_cookies构造成cookies。

接下来是获取URL,我们打开成绩页面,同样也是用F12去捕捉成绩页面的URL:


爬取学校教务处网站,提取并保存信息_第3张图片

或者其实可以直接从网址那里复制???不是很懂,因为有网友说其实获取真实URL会有点麻烦。。。这里也要回头复习,什么是真实URL?怎么获取?嗯,记一下。

到这里我们已经把所有请求页面要包含的信息都准备好,可以开始写请求代码了。我用的是requests库,感觉要比urllib2方便。

import requests
from bs4 import BeautifulSoup

header = {"User-Agent": "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/62.0.3202.94 Safari/537.36"}
cookies = {}
raw_cookies = "ASP.NET_SessionId=2gq0mryer************; UserTokeID=f716cffe-************-a84d-**********c"
for line in raw_cookies.split(';'): #用';'对字符串分割
        key, value = line.split('=', 1)
        cookies[key] = value
url = "http://202.115.133.***:805/********/Score/ScoreList.aspx"

r = requests.get(url, headers = header, cookies = cookies)

这样我们就完成了请求,接下来解析页面。

2:解析页面
打开成绩页面,F12下看Element选项,或者网页源代码,我们可以看出成绩页面的结构:如下图:


爬取学校教务处网站,提取并保存信息_第4张图片
image.png

右键审查元素,定位到元素标签。哇,这么多

  • ...
  • 标签,应该就是每门课的成绩信息了。我们点开具体看一下:


    爬取学校教务处网站,提取并保存信息_第5张图片
    image.png

    果然,没毛病老铁。

    接下来就好办了,思路是:用靓汤找到所有的

  • ...
  • 标签,然后循对每一个
  • ...
  • 里面的信息提取。嗯,上代码:

    soup = BeautifulSoup(r.text, "html.parser")
    items = soup.findAll('li', attrs = {'class': 'item'}
    for item in items:
            print(item.text)
    

    我们先来试试看输入结果:


    爬取学校教务处网站,提取并保存信息_第6张图片
    image.png

    你妹!!!什么鬼?!!!这一大堆的空格我可不能输进Excel啊!!!
    试试用split()切开:

    soup = BeautifulSoup(r.text, "html.parser")
    items = soup.findAll('li', attrs = {'class': 'item'}
    for item in items:
            print(item.text.split())
    
    out:
    
    爬取学校教务处网站,提取并保存信息_第7张图片
    image.png

    嗯~~~很好,列表形式的数据就好操作多了。为了能更加愉快地玩耍,我们可以把这些列表全放到一个新的列表里:

    data_list = []
    for item in items:
            data_list.append(item.text.split())
    

    看看输出:

    print(data_list)
    
    image.png

    很好,接下来就只要把数据写进Excel里面就成啦

    3:保存数据
    写入Excel操作我用到了xlwt,安装这个库也是有点小坑,具体解决方案网上有很多,不再赘述。上代码:

    book = xlwt.Workbook()
    sheet1 = book.add_sheet('sheet1', cell_overwrite_ok = True)
    #列表的每一行写入一门课成绩,最开始的行为0行,写入表格头:
    heads = ['学期', '课程编码', '课程名称', '教师', '学分', '成绩', '成绩类型', '绩点', '入库人', '入库时间']
    #这里write方法接受3个参数,分别为行、列、值。表格头部信息在第0行
    i = 0
    for head in heades:
            #依次将heades列表的每一个元素写入表格中
            sheet1.write(0, i, head)
            i += 1
    #从第1行开始写入成绩信息
    m = 1
    #对大列表里每一个小列表进行遍历,小列表保存有一门课的成绩信息,这样就能把所有课程成绩信息循环到。
    for list in data_list:
            n = 0
            #对小列表里每个元素进行遍历
            for info in list:
                    #将每个元素写入表格
                    sheet1.write(m, n, info)
                    n += 1
            m += 1
    book.save('grade.xls')
    

    这样全部代码就完成啦!下面是完整代码,本水笔代码代码像屎一样,没有一丁点封装。。。。。后面有时间再慢慢优化

    import requests
    from bs4 import BeautifulSoup
    import xlwt
    
    header = {'User-Agent': 'Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/62.0.3202.94 Safari/537.36'}
    raw_cookies = "ASP.NET_SessionId=2gq0mryer0o34wrmurek2dm3; UserTokeID=37efd17b-5a15-409f-93c5-8f9566d2b21d"
    
    cookie = {}
    for line in raw_cookies.split(';'):
        key, value = line.split("=", 1)
        cookie[key] = value
    url = "http://202.115.133.173:805/SearchInfo/Score/ScoreList.aspx"
    r = requests.get(url, headers=header, cookies = cookie)
    r.encoding = 'utf8'
    
    data_list = []
    soup = BeautifulSoup(r.text, "html.parser")
    items = soup.find_all('li', attrs={'class': 'item'})
    for item in items:
        data_list.append(items.text.split())
    
    book = xlwt.Workbook()
    sheet1 = book.add_sheet('sheet1', cell_overwrite_ok = True)
    heads = ['学期', '课程编码', '课程名称', '教师', '学分', '成绩', '成绩类型', '绩点', '入库人', '入库时间']
    i = 0
    for head in heads:
        sheet1.write(0, i, head)
        i += 1
    
    m = 1
    for list in data_list:
        n = 0
        for data in list:
            sheet1.write(m, n, data)
            n += 1
        m += 1
    book.save("chenzhida.xls")
    print("录入成功")
    

    成果如下:


    爬取学校教务处网站,提取并保存信息_第8张图片
    image.png

    遗留问题:
    有些课程的信息不全,比如没有教师的名字等等,这样录进Excel的时候信息会对不上表头。应该可以用某种替换方法,给空格占个位置,这样录进去的格式就能对的上表头。后面再处理吧~

    以下是本次爬取过程中遇到的一些坑,还有困惑,写下来提醒自己以后要解决:

    1. 使用cookies模拟登录自然会省事点,但是由于这个凭证只能短期有效,当需要爬取数据很多的时候,可能需要爬取十几天或者更久,这时cookies就不好用了,容易挂掉。这里需要学习post,学习分析账号密码提交,要是有加密怎么破解?遇到验证码怎么办?FROM DATA中每一项数据代表什么?遇到动态页面怎么破?(有大神教吗?)
    2. 如何获取真实URL,真实URL是什么?
    3. 表格数据有缺失怎么破
    4. 保存数据到本地。要学习常用的mongoDB。
    5. 学习其他的解析工具,Xpath
    6. 学习scrapy。

    另外,此次保存数据还花了老子大部分时间,记录一下犯蠢的过程:
    一开始我的思路是,把所有的课程成绩信息提取出来,放到一个总的表格里,然而当我实际做的时候,我发现:

    items = soup.findAll(r.text, "html.parser)
    data_list = []
    for item in items:
            data_list.append(item.text)
            print(data_list)
    

    返回的是:


    爬取学校教务处网站,提取并保存信息_第9张图片

    后来发现是输出的地方错了:应该是

    items = soup.findAll(r.text, "html.parser)
    data_list = []
    for item in items:
            data_list.append(item.text)
    print(data_list)
    

    for循环没掌握好。。。。
    但是这样输出的是:


    image.png

    还是不行呀,这些“ \xa0\r\n,\n\r\n ”是什么鬼???(其实可以用在末尾追加.spilt()方法,可以实现去掉空格和换行符)

    然后我又想到了可不可以用正则表达式提取内容?把所有内容提取出来放到一个表格中,和原来不同的是,这里大表格里面是没有小表格的。我们可以取10个元素取10个元素这样去做小表格。
    又开始折腾了:

    infos = re.findall(r'(.*?)
    ', str(items)) print(infos)

    结果:


    image.png

    emmmmmm......exo me????
    后来仔细一看网页源代码:


    爬取学校教务处网站,提取并保存信息_第10张图片
    image.png

    哦,原来有空格,而 . 是除了空格以外的任意字符,一般都要加re.S
    infos = re.findall(r'(.*?)
    ', str(items), re.S) print(infos)

    结果:


    image.png

    what the 你妹!这不和原来一样了吗?不过确实是一个大表格,但是
    \xa0\r\n \r\n 肿么破?机智的我想到用replace()试试看:

    infos = re.findall(r'(.*?)
    ', str(items), re.S) for info in infos: print(str(info).replace('\xa0\r\n', '').replace('\r\n', '').strip())
    爬取学校教务处网站,提取并保存信息_第11张图片
    image.png

    我好像发现了什么!!!原来的遗留问题貌似可以解决的!!!

    list = []
    infos = re.findall(r'(.*?)
    ', str(items), re.S) for info in infos: list.append(str(info).replace('\xa0\r\n', '').replace('\r\n', '').strip()) #把list按照每次取10个的数量,做成小表格,然后把这些小表格添加到new_list里面方便操作,这样的好处是,会把缺失信息的地方给站位,后面录进Excel的时候就不会对不上表头。 new_list = [list[i: i+10] for i in range(0, len(list), 10)] print(new_list)

    结果:


    image.png

    爬取学校教务处网站,提取并保存信息_第12张图片

    哈哈哈那我直接放完整代码了

    # -*- coding: utf-8 -*-
    import requests
    import  re
    from bs4 import BeautifulSoup
    import xlwt
    
    header = {'User-Agent': 'Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/62.0.3202.94 Safari/537.36'}
    raw_cookies = "ASP.NET_SessionId=2gq0mryer0o34wrmurek2dm3; UserTokeID=6412ebc3-5fde-44f5-b5e0-d0de28125591"
    url = "http://202.115.133.173:805/SearchInfo/Score/ScoreList.aspx"
    cookies = {}
    for line in raw_cookies.split(";"):
        key, value = line.split("=", 1)
        cookies[key] = value
    
    r = requests.get(url, headers = header, cookies = cookies)
    print(r.status_code)
    r.encoding = 'utf8'
    
    data_list = []
    soup = BeautifulSoup(r.text, "html.parser")
    items = soup.find_all('li', attrs = {'class': 'item'})
    
    list = []
    infos = re.findall(r'(.*?)
    ', str(items), re.S) for info in infos: list.append(str(info).replace('\xa0\r\n', '').replace('\r\n', '').strip()) new_list = [list[i: i+10] for i in range(0, len(list), 10)] print(new_list) book = xlwt.Workbook() sheet1 = book.add_sheet('shee1', cell_overwrite_ok=True) heads = ['学期', '课程编码', '课程名称', '教师', '学分', '成绩', '成绩类型', '绩点', '入库人', '入库时间'] s = 0 for head in heads: sheet1.write(0, s, head) s += 1 m = 1 for lists in new_list: n = 0 for data in lists: sheet1.write(m, n, data) n += 1 m += 1 book.save("stander.xls") print("录入成功")

    成果:


    爬取学校教务处网站,提取并保存信息_第13张图片
    image.png

    这样有些没有信息的地方也可以用空白来站位。
    finish!

    你可能感兴趣的:(爬取学校教务处网站,提取并保存信息)