一、实验方案设计

1、获得“2022软科中国大学排名”数据,从【软科排名】2022年最新软科中国大学排名|中国最好大学排名网页中获得排名数据信息,并将数据保存到csv文件中。

2、调用两个CSV文件,将他们合成一个文件,并按排名先后对其进行排序

3、将合并文件储存为txt文件和json文件

二、实验过程记录

1、获得“2022软科中国大学排名”数据

我们采用爬虫的方式在网站上进行数据收集,首先导入实验所需的包

import requestsimport refrom bs4 import BeautifulSoupimport pandas as pdimport time

下面进行数据收集操作,定义相关函数:

getHTMLText(url)该函数用来获取网页源代码,参数为网站链接,Timeout设置为30,解码方式为’utf-8’。

函数代码如下:

如果出现错误则返回空值,不会报错中断程序运行。

def getHTMLText(url):try:r = requests.get(url, timeout=30)r.raise_for_status()r.encoding = 'utf-8'return r.textexcept:return ""

观察网页HTML发现,我们需要的每条学校信息在标签

之间,学校的每条属性在

之间,下面是以北京师范大学为例的展示:

因此我们从HTML文件中获取学校信息,其中参数为源代码的HTML解析

def fillUnivList(soup):data = soup.find_all('tr')for tr in data:ltd = tr.find_all('td')if len(ltd)==0:continuesingleUniv = []for td in ltd:STR = td.find_all(string=re.compile("."))singleUniv.append(STR)singleUniv.append(td.string)allUniv.append(singleUniv)

将获取的每条数据放入我们建立的数组中。

获得数的数组后,我们定义函数所需的数据写入csv文件,writeUnivList(num,num1)其中参数是获取大学的排名,例如我们写(0,10)就是找1-10的大学信息,写入csv中,我们选取了排名,名称,属性等7个属性值作为CSV输出。当然也可以根据需要选择重要属性,其中我们就忽略了学校英文名称的信息。

def writeUnivList(num,num1):result = {"排名": [],"学校名称": [],"评价": [],# 985/211/双一流"省市": [],"类型": [],# 理工/综合/师范/农业"总分": [],"培养规模": []}for i in range(num,num1):u=allUniv[i]rank = u[1].replace(' ', '')name = u[2][1].replace(' ', '')value = u[2][10].replace(' ', '')city = u[4][0].replace(' ', '')type = u[6][0].replace(' ', '')score = u[8][0].replace(' ', '')scale = u[10][0].replace(' ', '')result["排名"].append(rank)result["学校名称"].append(name)result["评价"].append(value)result["省市"].append(city)result["类型"].append(type)result["总分"].append(score)result["培养规模"].append(scale)return result

最后通过主函数对上面的函数进行调用返回DataFrame后的数据,同时我们也将源代码中的回车和空格进行的删除。

def main(num,num1):url = 'https://www.shanghairanking.cn/rankings/bcur/2022'html = getHTMLText(url).replace('\n', '').replace(u'\xa0', '')soup = BeautifulSoup(html, "html.parser")fillUnivList(soup)df = pd.DataFrame(writeUnivList(num,num1))return df

分别写入Univrank1-10.csv文件和Univrank11-20.csv文件,同时调用进度条函数增加输出的可视化。

def Bar():scale = 50print("执行开始".center(scale // 2, '-'))#t = time.perf_counter()for i in range(scale + 1):a = '*' * ib = '.' * (scale - i)c = (i / scale) * 100#t -= time.perf_counter()print("\r{:^3.0f}% [{} -> {}] ".format(c, a, b), end=' ')time.sleep(0.02)#print("\n" + "执行结束".center(scale // 2, '-'))Bar()#main(0,10).to_csv("Univrank1-10.csv", index=False,encoding="utf_8_sig")main(20,30).to_csv("Univrank30-40.csv", index=False,encoding="utf_8_sig")print("\n文件写入成功!!!")print("执行结束".center(50 // 2, '-'))

2、合并两个文件

import pandas as pdr1= pd.read_csv('Univrank1-10.csv', encoding='utf-8')# 文件1r2= pd.read_csv('Univrank11-20.csv',encoding='utf-8')# 文件2def Combition(r1,r2):df = pd.concat([r1, r2])df.drop_duplicates()# 数据去重df = df.sort_values(axis=0, by="排名", ascending=True) #排名升序排列#df = df.sort_values(axis=0, by="总分", ascending=False)#按总分降序排列return df# r1.to_csv('Univrank.csv', index=False, header=True)# 第一个csv文件保留表头# r2.to_csv('Univrank.csv', index=False, header=False, mode='a+')# 第2个csv文件不保留表头,追加到合并文件后面Combition(r1,r2).to_csv('Univrank.csv',index=False, encoding="utf_8_sig")

将两个文件打开,定义一个Combition(r1,r2)函数,参数为需要合并的两个文件,利用concat()合并后,进行sort排序,可以用排名的升序或者总分的降序进行排列。

3、转存为txt文件

将csv文件写入txt有多种方式1)可以直接进行格式转换2)一行一行写入3)一个一个写入,为保证写入文件的整齐,我们采用一个一个写入的方式,由于中文字符不能直接利用center或者ljust进行对其,在尝试多种方法后我们定义一个函数用来中文格式化对齐:

import osdef duiqi(string,length):difference = length - len(string)# 计算限定长度时需要补齐多少个空格if difference == 0:# 若差值为0则不需要补return stringelif difference < 0:print('错误:限定的对齐长度小于字符串长度!')return Nonenew_string = ''space = ' 'for i in string:codes = ord(i)# 将字符转为ASCII或UNICODE编码if codes <= 126:# 若是半角字符new_string = new_string + chr(codes+65248) # 则转为全角else:new_string = new_string + i# 若是全角,则不转换return new_string + space*(difference)# 返回补齐空格后的字符串

参数分别是string我们要设定格式的字符串,length设定的长度,我们通过计算字符串的长度,再利用空格对不足length的进行补齐来对齐的方式,当然空格加在前面是右对齐,我们选择将空格加在后面形成左对齐的方式。

a = open('Univrank.csv', 'r',encoding='utf_8')data = csv.reader(a)with open('Univrank.txt', 'a+',encoding='utf_8') as f:for i in data:for x in i:#x = x.replace(' ', '')f.write(duiqi(x,20))print(type(x))#f.write(x)# f.write('\t\t\t\t\t')#f.write('\t')f.write('\n')a.close()
with open('Univrank.txt', 'r',encoding='utf_8') as f:print(f.read())

同时在每一条学校记录处换行,达到整齐的效果。

4、转存为Json文件

首先导入json包

将csv中数据放入数组中,每行用,隔开

fr=open("Univrank.csv","r",encoding='utf_8')ls=[]i = 0for line in fr:line=line.replace("\n","")ls.append(line.split(","))

将每一条学校的记录以键值对的方式,并把第一行索引作为字典的键,每行值作为值,储存到数组中.

写入Univrank.json文件,以json.dumps进行格式化。

三、实验结果分析及实验心得

1、获得“2022软科中国大学排名”数据

爬虫在获取数据时,由于下一页的url发生变化,所以我们通过程序最多只能获取到30名电子科技大学,后面的排名将无法获取程序将会报错,后续可以观察进入下一页后,url变化对程序进行优化。

这是获得的结果数据,由于我们写入文件时采用utf_8_sig编码,所以采用excl打开不会出现乱码的现象。

这是程序执行的界面,具有动态可视化的特点。

2、合并两个文件

我们进行合并后,进行排序,可以得到一个完整且按顺序排列的大学排名表格

我们在输出时去掉了index项,因此没有索引。

3、转存为txt文件

虽然尝试多种对齐方式,但在输出时仍然存在位移问题,因此仍需后续的优化操作,这是最终的输出结果。

4、转存为Json文件

我们首先尝试了直接存为json文件,结果如下,输出并不直观,

因此我们加入了dict()语句,以字典方式输出更直观、整齐。下面为输出结果。