访问网址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()