访问网址https://www.shanghairanking.cn/rankings,爬取排行榜数据,分析按区域的大学数量排行,得出有效结论。
- 爬取主榜数据并保存在文件中。
- 分析每个地区上榜大学的数量,保存在文件中。
- 分析前十名的地区的大学数量,绘制柱状图。
(4)说明爬虫爬取过程中可能涉及到的社会、健康、安全、法律以及文化问题,并并评价和说明分析结果对于社会、健康、安全、法律以及文化的影响,符合道德和社会公共利益,理解应承担的责任。
使用 requests 库进行爬取
import requests
from bs4 import BeautifulSoup
# 按间距中的绿色按钮以运行脚本。
if __name__ == '__main__':
# 发送HTTP GET请求获取网页内容
url = "https://www.shanghairanking.cn/rankings/bcur/202311"
response = requests.get(url)
# 解析HTML内容
soup = BeautifulSoup(response.text, "html.parser")
# 找到包含大学排行的表格
table = soup.find("table", class_="rk-table")
# 提取表格中的数据
data = []
# 表头
headers = table.find("thead").find_all("tr")
# 表格
tbody = table.find("tbody")
rows = tbody.find_all("tr")
for row in rows:
cols = row.find_all("td")
data.append([col.text.strip() for col in cols])
# 将数据保存到文件
with open("./data/university_rankings.txt", "w", encoding="ISO-8859-1") as file:
for entry in data:
file.write(f"{entry[0]}\t{entry[1]}\n")
但是此种爬取方式只能爬取第一页数据,比较受限。
网页改版,导致无法爬取整个数据,可以使用Selenium[6]和Chrome WebDriver作为爬虫工具,可以模拟浏览器的行为,通过代码进行控制翻页,然后再进行爬取每一页的数据。然后将每一页的数据加入数组,最后读完后进行数据持久化,将数据存储到电脑中相应的文件中,使用csv格式进行保存。
import csv
from selenium import webdriver
from selenium.webdriver.chrome.service import Service
from selenium.webdriver.common.by import By
def getFirstText(list):
try:
return list[0].strip()
except:
return ""
def getData(browser, data):
try:
for i in range(1, 31):
tr = browser.find_element(By.XPATH, '//*[@id="content-box"]/div[2]/table/tbody/tr[' + i.__str__() + ']')
id = tr.find_element(By.XPATH, './td[1]/div').text
name = tr.find_element(By.XPATH, './td[2]/div/div[2]/div[1]/div/div/a').text
province = tr.find_element(By.XPATH, './td[3]').text
type = tr.find_element(By.XPATH, './td[4]').text
score = tr.find_element(By.XPATH, './td[5]').text
data.append([id, name, province, type, score])
except:
print("不够30条了")
return data
def writeData(data):
# 打开文件,选择写入模式('w')
with open('../reptile/data/ranking.csv', 'w', newline='') as file:
writer = csv.writer(file)
writer.writerow(['排名', '大学名称', '省份', '类型', '分数'])
writer.writerows(data)
print("文件写入成功")
def main():
# url地址
url = 'https://www.shanghairanking.cn/rankings/bcur/202311'
headers = {
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/114.0.0.0 Safari/537.36 Edg/114.0.1823.37'
}
# 定义chrome驱动去地址
path = Service('chromedriver.exe')
data = []
# 创建浏览器操作对象
browser = webdriver.Chrome(service=path)
browser.get(url=url)
for i in range(1, 21):
# time.sleep(3)
getData(browser, data)
if i in [1, 2, 3, 18, 19, 20]:
alink = browser.find_element(By.XPATH,
'/html/body/div/div/div/div[2]/div/div[3]/div[2]/div[1]/div/ul/li[9]/a')
elif i in [4, 17]:
alink = browser.find_element(By.XPATH,
'/html/body/div/div/div/div[2]/div/div[3]/div[2]/div[1]/div/ul/li[10]/a')
else:
alink = browser.find_element(By.XPATH,
'/html/body/div/div/div/div[2]/div/div[3]/div[2]/div[1]/div/ul/li[11]/a')
alink.click()
print("第", i, '页已经读取完成')
writeData(data)
if __name__ == '__main__':
main()
(2)分析每个地区上榜大学的数量,保存在文件中。
# (2)分析每个地区上榜大学的数量,保存在文件中。
import pandas as pd
# 分地区进行排序
df = pd.read_csv("../reptile/data/ranking.csv", encoding='gbk')
# 分组统计
data = pd.DataFrame(pd.value_counts(df['省份']))
# 建立新索引
data = data.reset_index(drop=False)
data.index = data.index + 1
# 生成dataframe对象
names = ['省份', '数量']
data.columns = names
# 保存文件
data.to_csv("../reptile/data/GroupStatistics.csv", encoding='gbk')
(3)分析前十名的地区的大学数量,绘制柱状图。
# (3)分析前十名的地区的大学数量,绘制柱状图。
import pandas as pd
import matplotlib.pyplot as plt
# 分地区进行排序
df = pd.read_csv("../reptile/data/ranking.csv", encoding='gbk')
# 计数并按数量降序排序
top_10 = df['省份'].value_counts().head(10)
# 设置字体
plt.rcParams['font.sans-serif'] = ['SimHei'] # 设置中文字体为SimHei
# 绘制柱状图
plt.bar(top_10.index, top_10.values)
# 设置图形标题和坐标轴标签
plt.title("Top 10 Regions with Most Universities")
plt.xlabel("Region")
plt.ylabel("Number of Universities")
# 旋转地区标签,以防止重叠
plt.xticks(rotation=45)
# 显示图形
plt.show()
(3)分析前十名的地区的大学数量,绘制柱状图。
# (3)分析前十名的地区的大学数量,绘制柱状图。
import pandas as pd
import matplotlib.pyplot as plt
# 分地区进行排序
df = pd.read_csv("../reptile/data/ranking.csv", encoding='gbk')
# 计数并按数量降序排序
top_10 = df['省份'].value_counts().head(10)
# 设置字体
plt.rcParams['font.sans-serif'] = ['SimHei'] # 设置中文字体为SimHei
# 设置字体
plt.rcParams['font.sans-serif'] = ['SimHei'] # 设置中文字体为SimHei
# 绘制圆饼图
plt.pie(top_10.values, labels=top_10.index, autopct='%1.1f%%')
# 添加标题
plt.title('前10名省份大学占比')
# 显示图形
plt.show()