Python爬虫入门之2022软科中国大学排名爬取保存到csv文件

一、实验方案设计

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发现,我们需要的每条学校信息在标签<tr>之间,学校的每条属性在<td>之间,下面是以北京师范大学为例的展示:

因此我们从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()语句,以字典方式输出更直观、整齐。下面为输出结果。

文章出处登录后可见!

已经登录?立即刷新

共计人评分,平均

到目前为止还没有投票!成为第一位评论此文章。

(0)
青葱年少的头像青葱年少普通用户
上一篇 2023年6月6日
下一篇 2023年6月6日

相关推荐