1、获得“2022软科中国大学排名”数据,从【软科排名】2022年最新软科中国大学排名|中国最好大学排名网页中获得排名数据信息,并将数据保存到csv文件中。
2、调用两个CSV文件,将他们合成一个文件,并按排名先后对其进行排序
3、将合并文件储存为txt文件和json文件
我们采用爬虫的方式在网站上进行数据收集,首先导入实验所需的包
import requests import re from bs4 import BeautifulSoup import pandas as pd import 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.text except: 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: continue singleUniv = [] 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 = 50 print("执行开始".center(scale // 2, '-')) #t = time.perf_counter() for i in range(scale + 1): a = '*' * i b = '.' * (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, '-'))
import pandas as pd r1= pd.read_csv('Univrank1-10.csv', encoding='utf-8') # 文件1 r2= pd.read_csv('Univrank11-20.csv',encoding='utf-8') # 文件2 def 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排序,可以用排名的升序或者总分的降序进行排列。
将csv文件写入txt有多种方式1)可以直接进行格式转换2)一行一行写入3)一个一个写入,为保证写入文件的整齐,我们采用一个一个写入的方式,由于中文字符不能直接利用center或者ljust进行对其,在尝试多种方法后我们定义一个函数用来中文格式化对齐:
import os def duiqi(string,length): difference = length - len(string) # 计算限定长度时需要补齐多少个空格 if difference == 0: # 若差值为0则不需要补 return string elif difference < 0: print('错误:限定的对齐长度小于字符串长度!') return None new_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())
同时在每一条学校记录处换行,达到整齐的效果。
首先导入json包
将csv中数据放入数组中,每行用,隔开
fr=open("Univrank.csv","r",encoding='utf_8') ls=[] i = 0 for line in fr: line=line.replace("\n","") ls.append(line.split(","))
将每一条学校的记录以键值对的方式,并把第一行索引作为字典的键,每行值作为值,储存到数组中.
写入Univrank.json文件,以json.dumps进行格式化。
爬虫在获取数据时,由于下一页的url发生变化,所以我们通过程序最多只能获取到30名电子科技大学,后面的排名将无法获取程序将会报错,后续可以观察进入下一页后,url变化对程序进行优化。
这是获得的结果数据,由于我们写入文件时采用utf_8_sig编码,所以采用excl打开不会出现乱码的现象。
这是程序执行的界面,具有动态可视化的特点。
我们进行合并后,进行排序,可以得到一个完整且按顺序排列的大学排名表格
我们在输出时去掉了index项,因此没有索引。
虽然尝试多种对齐方式,但在输出时仍然存在位移问题,因此仍需后续的优化操作,这是最终的输出结果。
我们首先尝试了直接存为json文件,结果如下,输出并不直观,
因此我们加入了dict()语句,以字典方式输出更直观、整齐。下面为输出结果。