一、实验方案设计
1、获得“2022软科中国大学排名”数据,从【软科排名】2022年最新软科中国大学排名|中国最好大学排名网页中获得排名数据信息,并将数据保存到csv文件中。
2、调用两个CSV文件,将他们合成一个文件,并按排名先后对其进行排序
3、将合并文件储存为txt文件和json文件
二、实验过程记录
1****、获得“2022软科中国大学排名”数据
我们采用爬虫的方式在网站上进行数据收集,首先导入实验所需的包
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, '-'))
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排序,可以用排名的升序或者总分的降序进行排列。
3****、转存为txt文件
将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())
同时在每一条学校记录处换行,达到整齐的效果。
4****、转存为Json文件
首先导入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进行格式化。
三、实验结果分析及实验心得
1****、获得“2022软科中国大学排名”数据
爬虫在获取数据时,由于下一页的url发生变化,所以我们通过程序最多只能获取到30名电子科技大学,后面的排名将无法获取程序将会报错,后续可以观察进入下一页后,url变化对程序进行优化。
这是获得的结果数据,由于我们写入文件时采用utf_8_sig编码,所以采用excl打开不会出现乱码的现象。
这是程序执行的界面,具有动态可视化的特点。
2****、合并两个文件
我们进行合并后,进行排序,可以得到一个完整且按顺序排列的大学排名表格
我们在输出时去掉了index项,因此没有索引。
3****、转存为txt文件
虽然尝试多种对齐方式,但在输出时仍然存在位移问题,因此仍需后续的优化操作,这是最终的输出结果。
4****、转存为Json文件
我们首先尝试了直接存为json文件,结果如下,输出并不直观,
因此我们加入了dict()语句,以字典方式输出更直观、整齐。下面为输出结果。
版权归原作者 Maca Baka138 所有, 如有侵权,请联系我们删除。