某C9高校研究生学位申请公示网站信息分析(1)——Python数据爬取


受到疫情影响,很多高校还在放假中,但毕业生工作却并没有停下来。这里以国内某C9高校为例,通过公示信息网页进行学位申请信息的爬取。

一、确定业务需求

1、网页爬取目标:

获取公示名单中所有人的关键公示信息

2、目标网页结构:

首先来看一下目标网页:
结构很简单,公示网页如下
点击姓名进入超链接网页,可以看到博士、学硕、专硕三类学位的公示信息有明显差异
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

3、进一步明确目标信息:

选择共有且价值的信息:学号、姓名、所在院系、申请专业/工程领域、论文题目

二、关键功能点拆解

1、计算运行时间:datetime库

由于爬取网页有300多个,这里我用datetime库计算运行时间,方便优化代码后性能比较

import datetime

starttime = datetime.datetime.now()
......
endtime = datetime.datetime.now()
cost=endtime - starttime

print('The time cost: ',cost)

2、读写文档

f_res=open("C:/Users/....../get_ID.csv","w",encoding='gb18030',errors='ignore')  #解决文本编码问题
title="学号"+","+"姓名"+","+"所在院系"+","+"申请专业/工程邻域"+","+"论文题目"
f_res.writelines(title+"\n")  #打印标题行,增加文档可读性
......
f_res.close()

“UnicodeEncodeError”编码错误的解决方案

由于网页文本编码问题,我原始代码读取文件时出现“UnicodeEncodeError”编码错误,如下图:

这里的最终解决方案是:f_res=open(“C:/Users/…/get_ID.csv”,“w”,encoding=‘gb18030’,errors=‘ignore’)

在这里插入图片描述

使用Python读文件,我们一般使用utf-8编码,有时会出现gbk,utf-8的编码格式读取都不对,运行出错。

解决方案:

1.选择编码范围更广的gb18030
file = open(‘abc.txt’,encoding=‘gb18030’)

2.仍不能解决,可以使用‘ignore’属性进行忽略
file = open(‘abc.txt’,encoding=‘gb18030’,errors=‘ignore’)

此处参考博客:
(1)Python文本编码问题
(2)Python文本文件读写操作时的字符编码问题

3、增加互动效果

有时候我们代码运行过程中我们可能不确定代码运行状态,这里我引入print打印运行状态。这对等待程序运行中的我们非常有趣

print("数据获取开始......")
......
print("找到学号"+str(http)+"的信息如下:")
......
print("继续爬取下一条信息......")
......
print("网页信息采集完成")

效果如下:

在这里插入图片描述

4、网页数据获取:requests库

(1)公示名单网页(单一网页):

url = "http://......gongShiList.asp"
headers = {'user-agent': 'Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/80.0.3987.106 Safari/537.36'}
res = requests.get(url, headers=headers)

(2)公示人具体信息网页(批量网页):

首先分析网页网址特征,发现变化项为公示人学号:
在这里插入图片描述
那么如何获取学号信息?
这里想到直接在公示名单网页获取每一个超链接的网址,这里发现网址为不完全显示,那么我这里只取最后的学号信息。
具体操作方法我在上一篇博客python抓取页面文本及图片超链接中讲到了。在下面我也会在简单讲一下
在这里插入图片描述利用我们提取的学号信息生成目标url,如下方案一

另外,因为学号是固定的,我们可以利用for循环对学号进行逐个搜索,如下方案二。但是这种方法比较笨,而且存在大量无效项,花费时间也很长,在这里不适合使用。

方案一:网页中变动项用列表存储,for循环读取每一条,如:
for item in soup_item:
        url = "http://....../gongShiShowStudentInfo.asp?studentId="+str(item)  #这里一定要以str类型表示
        headers={......}
        res = requests.get(url, headers=headers)

方案二:对于按一定规律进行变化,for循环.如:
list_co=["BA","BO","BZ","SA","SB","SM"]  #学号代码
	for l_c in range(len(list_co)):  #循环数为列表长度
		for i in range(16,19):
			for j in range(225001,225500):#注意Python不能处理以0开头的数字字符串,也就无法识别range(001,500),所以前面数字也需要加上 
				url = "http://....../gongShiShowStudentInfo.asp?studentId="+list_co[LC]+str(i)+str(j)
				headers = {......}
				res = requests.get(url, headers=headers)

4、网页数据解析:BeautifulSoup库

(1)公示网页超链接提取:

这里实际上我们提取的是超链接中的学号信息,在上面已经讲到了原因

url_id = "......"
headers = {......}
res_id = requests.get(url_id, headers=headers)
soup_id = BeautifulSoup(res_id.text,'lxml')  #将爬取的网页信息(res_id.text)用BS库进行解析
soup_name_herf=soup_id.find_all("a")  #精准的解析标签,在数据中查找超链接标签"a",并存入新变量
for herf_http in soup_name_herf:  #从新变量中逐个取出其中的标签"a"
    http = herf_http.get('href')[-10:]   #获取超链接标签中的herf网址信息,并提取其中倒数第十个及之后的数据
    print(http)

爬取结果:
在这里插入图片描述
推荐参考学习资料
(1)Python爬虫之解析网页:常用的类库为lxml, BeautifulSoup, re(正则)
(2)python爬虫基础–获取并解析网页

(2)网页中公示人信息提取:

首先爬取每一个网页的数据,并用bs库解析

url = "http://....../gongShiShowStudentInfo.asp?studentId="+str(http)
res = requests.get(url, headers=headers)
soup = BeautifulSoup(res.text,'lxml')

然后分析网页信息:

在这里插入图片描述
在这里插入图片描述
分析发现:除了博士的论文信息在中,其他目标信息都存在标签中。

这里使用**soup.find_all(“tag”)[n].get_text()**获取tag标签的指定位置n中的内容

可以用如下方法查找指定位置
在这里插入图片描述

import requests
from bs4 import BeautifulSoup
import datetime

headers = {'user-agent': 'Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/80.0.3987.106 Safari/537.36'}
url = "http://....../gongShiShowStudentInfo.asp?studentId=BA07002016"
res = requests.get(url, headers=headers)
soup = BeautifulSoup(res.text,'lxml')
s=soup.find_all('td', colspan="3")
print(s)
for i in range(len(s)):
    s_no=soup.find_all('td', colspan="3")[i].get_text()
    print("位置:",i,s_no)

由于博士和硕士的论文题目所在标签不一致,所以这里需要分开处理论文信息。

具体代码方法如下:

try:
    print("找到学号"+str(http)+"的信息如下:")
    s_no=soup.find_all('td', colspan="3")[0].get_text() #找到学号信息
    s_name=soup.find_all('td', colspan="3")[1].get_text() #找到姓名信息
    s_coll=soup.find_all('td', colspan="3")[2].get_text() #找到所在院系信息
    s_en=soup.find_all('td', colspan="3")[3].get_text() #找到申请专业/工程邻域信息
    if soup.find_all('td', colspan="3")[4].get_text()=="主要创新点":  #识别出博士
        s_pap=soup.find_all('td', colspan="2")[0].get_text()  #找到博士的论文题目信息
        print("学号:"+s_no+","+"姓名:"+s_name+","+"所在院系:"+s_coll+","+"申请专业:"+s_en+","+"论文题目:"+s_pap)   #打印信息,同时增加代码运行中的交互感
        txt=s_no+","+s_name+","+s_coll+","+s_en+","+s_pap #将结果以字符串连接
        f_res.writelines(txt+"\n") #将结果写入文档,并换行
    else:  #找到博士外的网页格式
        s_pap=soup.find_all('td', colspan="3")[4].get_text()  #找到论文题目信息
        print("学号:"+s_no+","+"姓名:"+s_name+","+"所在院系:"+s_coll+","+"申请专业/工程邻域:"+s_en+","+"论文题目:"+s_pap)
        txt=s_no+","+s_name+","+s_coll+","+s_en+","+s_pap
        f_res.writelines(txt+"\n")
    print("继续爬取下一条信息......")
except:
    continue

这里try … except…是为了防止报错。

到这里数据爬取就完成了。

这部分也可用正则表达式进行分析

三、结果展示

1、Jupyter界面结果

在这里插入图片描述
在这里插入图片描述
一共用时38秒

2、【爬取效果动态展示】:

在这里插入图片描述结果展示,一共获取342条数据:
在这里插入图片描述
验证名单完整性:
直接爬取公示名单页面所有的人名,利用excel的突出显示重复项与前面的数据进行对比,发现全部都爬取到了
在这里插入图片描述

四、完整代码

import requests
from bs4 import BeautifulSoup
import datetime

def get_res():
    url_id = "http://....../gongShiList.asp"
    headers = {'user-agent': 'Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/80.0.3987.106 Safari/537.36'}
    res_id = requests.get(url_id, headers=headers)
    soup_id = BeautifulSoup(res_id.text,'lxml')
    soup_name_herf=soup_id.find_all("a")
    for herf_http in soup_name_herf:
        http = herf_http.get('href')[-10:]
        url = "http://....../gongShiShowStudentInfo.asp?studentId="+str(http)
        res = requests.get(url, headers=headers)
        soup = BeautifulSoup(res.text,'lxml')
        try:
            print("找到学号"+str(http)+"的信息如下:")
            s_no=soup.find_all('td', colspan="3")[0].get_text()
            s_name=soup.find_all('td', colspan="3")[1].get_text()
            s_coll=soup.find_all('td', colspan="3")[2].get_text()
            s_en=soup.find_all('td', colspan="3")[3].get_text()
            if soup.find_all('td', colspan="3")[4].get_text()=="主要创新点":
                s_pap=soup.find_all('td', colspan="2")[0].get_text()
                print("学号:"+s_no+","+"姓名:"+s_name+","+"所在院系:"+s_coll+","+"申请专业:"+s_en+","+"论文题目:"+s_pap)
                txt=s_no+","+s_name+","+s_coll+","+s_en+","+s_pap
                f_res.writelines(txt+"\n")
            else:
                s_pap=soup.find_all('td', colspan="3")[4].get_text()
                print("学号:"+s_no+","+"姓名:"+s_name+","+"所在院系:"+s_coll+","+"申请专业/工程邻域:"+s_en+","+"论文题目:"+s_pap)
                txt=s_no+","+s_name+","+s_coll+","+s_en+","+s_pap
                f_res.writelines(txt+"\n")
            print("继续爬取下一条信息......")
        except:
            continue

if __name__=="__main__":
    starttime = datetime.datetime.now()
    f_res=open("C:/....../get_ID.csv","w",encoding='gb18030',errors='ignore')
    title="学号"+","+"姓名"+","+"所在院系"+","+"申请专业/工程邻域"+","+"论文题目"
    f_res.writelines(title+"\n")
    print("数据获取开始......")
    get_res()
    print("网页信息采集完成")
    f_res.close()
    endtime = datetime.datetime.now()
    cost=endtime - starttime
    print('The time cost: ',cost)

五、下一篇博客进行爬取数据的可视化分析

发布了50 篇原创文章 · 获赞 14 · 访问量 7939

猜你喜欢

转载自blog.csdn.net/yeyuanxiaoxin/article/details/104883873
C9