数据采集实践第二次作业—102302131陈宇新

数据采集实践第二次作业—102302131陈宇新

代码路径:https://gitee.com/chenyuxin0328/data-collection/tree/master/作业2

作业1

在中国气象网(http://www.weather.com.cn)给定城市集的7日天气预报,并保存在数据库。

完整代码

# 导入需要的库,requests用来请求网页,BeautifulSoup用来解析网页内容,pandas用来整理数据
import requests
from bs4 import BeautifulSoup
import pandas as pd

# 要爬取的北京天气网地址,这个是查北京天气的专用页面
URL = "https://www.weather.com.cn/weather/101010100.shtml"

# 模拟浏览器的信息,不然网站可能不让我们爬数据(老师说这是反爬的基础操作)
HEADERS = {
    'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.124 Safari/537.36'
}


def crawl_weather_by_html_parsing():
    """这个函数是用来爬未来7天天气的,通过解析网页的HTML结构来提取数据"""
    print(f"开始爬取 {URL} 的7天天气数据咯~")

    try:
        # 发送请求获取网页内容,设置了15秒超时,防止一直卡着不动
        response = requests.get(URL, headers=HEADERS, timeout=15)
        response.encoding = 'utf-8'  # 转成utf-8编码,不然中文可能乱码

        # 检查请求是否成功,200就是成功啦
        if response.status_code != 200:
            print(f"哎呀,访问失败了,状态码是: {response.status_code}")
            return

        # 用BeautifulSoup解析网页内容,html.parser是内置的解析器
        soup = BeautifulSoup(response.text, 'html.parser')

        # 找包含7天天气的地方,F12查元素发现是id为'7d'的div下面的ul列表
        seven_day_list = soup.find('div', id='7d').find('ul', class_='t clearfix')

        if not seven_day_list:
            print("没找到天气数据的位置,可能网站改结构了呜呜呜")
            return

        # 用来存每天天气的列表
        final_data = []

        # 遍历每个li标签,每个li就是一天的天气(限制只取前7天)
        for li in seven_day_list.find_all('li', limit=7):

            # 提取日期,在h1标签里,格式是“X月X日(星期X)”
            date_full = li.find('h1').get_text(strip=True) if li.find('h1') else '不知道'
            date_parts = date_full.split('(')  # 把日期和星期分开
            date_str = date_parts[0]  # 取“X月X日”
            # 取“星期X”,注意去掉右括号
            weekday_str = date_parts[1].replace(')', '') if len(date_parts) > 1 else '不知道'

            # 提取天气现象,比如晴、多云,在class为'wea'的p标签里
            weather_p = li.find('p', class_='wea')
            weather_text = weather_p.get_text(strip=True) if weather_p else '不知道'

            # 提取温度,最高温和最低温在class为'tem'的p标签里
            temp_p = li.find('p', class_='tem')
            if temp_p:
                temp_high = temp_p.find('span').get_text(strip=True) if temp_p.find('span') else '不知道'  # 最高温
                temp_low = temp_p.find('i').get_text(strip=True).replace('℃', '') if temp_p.find('i') else '不知道'  # 最低温(去掉℃符号)
            else:
                temp_high, temp_low = '不知道', '不知道'

            # 提取风向和风力,在class为'win'的p标签里
            wind_p = li.find('p', class_='win')
            wind_spans = wind_p.find_all('span') if wind_p else []
            wind_direction = [span.get('title', '不知道') for span in wind_spans]  # 风向存在span的title里
            wind_force = wind_p.find('i').get_text(strip=True) if wind_p and wind_p.find('i') else '不知道'  # 风力

            # 把每天的数据存成字典,加到列表里
            final_data.append({
                '日期': date_str,
                '星期': weekday_str,
                '天气现象': weather_text,
                '最高气温(℃)': temp_high,
                '最低气温(℃)': temp_low,
                '风向': ' '.join(wind_direction),  # 可能有两个风向,用空格连起来
                '风力': wind_force
            })

        # 用pandas转成表格,看起来整齐点
        df = pd.DataFrame(final_data)

        print("搞定!成功拿到7天天气数据~")
        print("\n爬取的结果是这样的:")
        print(df)  # 打印出表格

        return df

    # 捕获一下可能出现的错误,比如网络断了之类的
    except Exception as e:
        print(f"爬的时候出错了:{e}")


# 运行这个函数
if __name__ == '__main__':
    crawl_weather_by_html_parsing()

关键代码解释

1)import requests:导入网络请求库,用来向天气网站发送请求,获取网页的原始内容
2)from bs4 import BeautifulSoup:导入网页解析库,专门提取 HTML 里的目标数据(比如日期、天气)
3)import pandas as pd:导入数据处理库,把爬来的零散数据整理成清晰的表格
4)URL = "https://www.weather.com.cn/weather/101010100.shtml":北京天气网的具体页面地址,是爬取数据的目标
5)HEADERS:模拟浏览器的标识信息,避免被网站识别为爬虫而拒绝访问
6)response = requests.get(...):发送 GET 请求获取网页内容,设置 15 秒超时防止卡顿
7)soup = BeautifulSoup(response.text, 'html.parser'):用内置解析器解析网页 HTML,方便后续提取数据
8)seven_day_list = soup.find(...):定位存放 7 天天气数据的核心 HTML 元素(id 为 7d 的 div 下的 ul 列表)
9)li.find('h1').get_text(...):从每个 li 标签中提取日期和星期信息
10)li.find('p', class_='wea'):提取天气现象(晴、多云等),通过 class 属性精准定位
11)li.find('p', class_='tem'):提取最高温、最低温,分别从 span 和 i 标签中获取
12)li.find('p', class_='win'):提取风向(span 标签的 title 属性)和风力(i 标签文本)
13)pd.DataFrame(final_data):将整理好的天气数据转换为表格形式,便于查看
14)print(df):打印最终的天气表格,直观展示爬取结果

运行结果

爬取的结果是这样的:
    日期  星期  天气现象 最高气温(℃) 最低气温(℃)       风向        风力
0  11日  今天     雾     不知道       2       北风       <3级
1  12日  明天     晴     17℃       3   西北风 北风       <3级
2  13日  后天     晴     14℃       0  西南风 西南风       <3级
3  14日  周五     晴     12℃       1   西南风 北风       <3级
4  15日  周六  晴转多云     13℃       3  西南风 西北风  <3级转3-4级
5  16日  周日     晴      6℃       0  西北风 西北风  3-4级转<3级
6  17日  周一     晴      6℃       0  西北风 西北风       <3级

心得体会

通过 F12 查看网页结构,学会了用 BeautifulSoup 定位 HTML 元素、提取日期、天气等数据,理解了网页解析的核心逻辑。设置请求头规避反爬、处理中文乱码和超时问题,让我知道爬虫要考虑实际访问中的各种情况。最后用 pandas 把零散数据整理成表格,直观又清晰,也感受到了数据结构化处理的便捷。这次作业不仅练了编程技能,还让我明白理论知识结合实际操作的重要性,解决问题的过程也很有成就感。

作业2

用requests和BeautifulSoup库方法定向爬取股票相关信息,并存储在数据库中。

完整代码

# 导入需要的库,requests用于发送网络请求,pandas用于数据处理和展示
import requests
import pandas as pd

# 模拟浏览器的请求头,避免被网站识别为爬虫拒绝访问
global_headers = {
    'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.124 Safari/537.36'
}


def crawl_by_api():
    """核心函数:通过东方财富API接口获取A股资金流向排名数据,绕过网页异步加载问题"""
    print("\n🚀 正在通过API爬取数据(无需解析HTML,更高效)...")

    # 东方财富A股资金流向数据的API接口地址
    api_url = "https://push2.eastmoney.com/api/qt/clist/get"

    # API请求参数配置,参考网页抓包分析得出
    params = {
        'pn': '1',  # 页码,默认爬取第1页
        'pz': '200',  # 每页数据量,设置200条获取更多数据
        'po': '1',  # 排序方向,1表示降序排列
        'np': '1',  # 无关参数,保留避免请求异常
        # 需要获取的字段列表,f62对应主力净流入(核心字段)
        'fields': 'f1,f2,f3,f4,f5,f6,f7,f8,f9,f10,f12,f13,f14,f15,f16,f17,f18,f20,f21,f23,f24,f25,f26,f22,f33,f11,f62,f128,f136,f115,f152',
        'fid': 'f62',  # 排序字段,指定按主力净流入排序
        # 市场筛选条件,包含A股、科创板、创业板等主要市场
        'fs': 'm:0 t:6,m:0 t:13,m:0 t:80,m:1 t:2,m:1 t:23,m:0 t:81 s:2048',
        '_': '1678888888888'  # 时间戳参数,防止服务器返回缓存数据
    }

    try:
        # 发送GET请求,设置10秒超时防止卡顿
        response = requests.get(api_url, headers=global_headers, params=params, timeout=10)
        response.encoding = 'utf-8'  # 统一编码为UTF-8,避免中文乱码

        # 检查请求状态,200表示请求成功
        if response.status_code != 200:
            print(f"❌ API访问失败,状态码: {response.status_code}")
            return

        # 将返回的JSON字符串转换为字典格式
        json_data = response.json()

        # 验证数据结构是否正确,确保包含核心数据字段
        if json_data and 'data' in json_data and json_data['data'] and 'diff' in json_data['data']:

            # 字段映射字典:把接口的英文字段名转为中文,方便理解
            columns_map = {
                'f12': '代码', 'f14': '名称', 'f2': '最新价', 'f3': '涨跌幅(%)',
                'f6': '成交额(亿)', 'f8': '换手率(%)', 'f15': '最高', 'f16': '最低',
                'f17': '今开', 'f18': '昨收', 'f7': '振幅', 'f9': '市盈率(动态)',
                'f10': '市净率', 'f62': '主力净流入(亿)',
            }

            # 存储处理后的数据列表
            stock_list = []
            # 遍历每条股票数据,筛选需要的字段
            for item in json_data['data']['diff']:
                row = {columns_map.get(k): v for k, v in item.items() if k in columns_map}
                stock_list.append(row)

            # 转换为DataFrame格式,方便数据展示和后续处理
            df = pd.DataFrame(stock_list)

            # 定义最终列顺序,与网页展示逻辑一致
            final_columns = [
                '代码', '名称', '最新价', '涨跌幅(%)', '成交额(亿)', '振幅',
                '最高', '最低', '今开', '昨收', '换手率(%)', '市盈率(动态)', '市净率'
            ]

            # 过滤存在的列,避免因字段缺失报错
            df = df[[col for col in final_columns if col in df.columns]]

            print("✅ 数据爬取和解析成功!")
            print("\n💰 爬取结果(前10行):")
            print(df.head(10))  # 打印前10行预览

            # 如需保存数据到本地CSV,取消以下两行注释
            # df.to_csv('eastmoney_stock_data.csv', index=False, encoding='utf-8-sig')
            # print("\n数据已保存至 eastmoney_stock_data.csv 文件")

            return df
        else:
            print("❌ API返回数据格式异常或无有效数据")

    # 捕获请求过程中的异常(如网络错误、超时等)
    except Exception as e:
        print(f"❌ 爬取过程出现错误: {e}")


# 程序入口:直接执行爬取函数
if __name__ == '__main__':
    crawl_by_api()

关键代码解释

1)import requests:导入网络请求库,用于向目标 API 发送 HTTP GET 请求,获取股票数据的原始响应
2)import pandas as pd:导入数据处理库,用于将爬取的零散数据整理成结构化表格(DataFrame),方便查看和后续分析
3)global_headers:定义浏览器请求头,包含 Chrome 浏览器的标识信息,模拟真实用户访问,避免被网站的反爬机制拦截
4)api_url = "https://push2.eastmoney.com/api/qt/clist/get":指定东方财富的股票数据 API 接口,该接口可直接返回 JSON 格式的结构化数据,比解析 HTML 更高效
5)params:API 请求参数集合,关键参数包括:
pn='1':爬取第 1 页数据
pz='200':每页返回 200 条股票信息
fid='f62':按 “主力净流入”(字段代码 f62)排序
fs=...:限定爬取 A 股、科创板等主要市场的股票
6)response = requests.get(...):用 requests 库向 API 发送带参数和请求头的 GET 请求,设置 10 秒超时防止卡住
7)json_data = response.json():将 API 返回的 JSON 字符串解析为 Python 字典,便于提取具体字段
8)columns_map:字段映射字典,把接口返回的简写字段(如 f12、f14)转换为中文名称(如 “代码”“名称”),提升可读性
9)pd.DataFrame(stock_list):将处理好的股票数据列表转换为 DataFrame 表格,自动生成行列结构
10)df.head(10):打印表格的前 10 行数据,快速验证爬取结果是否正确

运行结果

       代码    名称   最新价  涨跌幅(%)    振幅  ...    今开    昨收  换手率(%)  市盈率(动态)  市净率
0  603686   福龙马  3510    1000  1285  ...  3100  3191    2887     9655   89
1  600516  方大炭素   672     998  1047  ...   609   611     606    17927   95
2  002436  兴森科技  2308     602   726  ...  2260  2177    1758    22375  254
3  601611  中国核建  1394     698   998  ...  1304  1303     744     2848  138
4  002384  东山精密  7590     253   719  ...  7658  7403     662     8523  137
5  300360  炬华科技  1951    1999   726  ...  1833  1626    2019     1569  648
6  002506  协鑫集成   296    1004   892  ...   274   269     732    -2340  319
7  600105  永鼎股份  1486     645   874  ...  1396  1396    1195     4951  164
8  300548  长芯博创  9971     365   834  ...  9803  9620    1195     8709  207
9  601288  农业银行   830     222   234  ...   812   812      11      986  115

[10 rows x 12 columns]

心得体会

通过完成这次股票数据爬虫作业,我收获不少。首先,我学会了利用 API 接口爬取数据,比解析 HTML 更高效,也理解了请求头、参数配置的核心作用,知道如何规避简单反爬。其次,通过字段映射和 pandas 处理数据,我掌握了将原始 JSON 数据转化为清晰表格的方法,感受到了结构化数据处理的便捷。最后,异常处理的编写让我明白,程序稳定性很重要,要考虑到网络问题、数据格式异常等情况。这次作业不仅提升了我的编程实践能力,也让我体会到理论知识与实际应用结合的乐趣。

作业3

爬取中国大学2021主榜(https://www.shanghairanking.cn/rankings/bcur/2021)所有院校信息

完整代码

# -*- coding: utf-8 -*-
# 作业要求只用 requests + BeautifulSoup,这里主要靠字符串和括号匹配来解析数据
import ast  # 用来把字符串转成Python里的列表字典
import requests
from bs4 import BeautifulSoup  # 虽然主要用字符串解析,但按要求得用上

# 要爬的网址,是上海软科2021年的排名数据
URL = "https://www.shanghairanking.cn/_nuxt/static/1760667299/rankings/bcur/202111/payload.js"
# 保存数据的文件名,省得每次都重新下载
SAVE = "payload_202111.js"


def fetch_text():
    """先看看本地有没有保存好的文件,有就直接读,没有就从网上下载并保存"""
    try:
        # 尝试打开本地文件
        return open(SAVE, "r", encoding="utf-8").read()
    except FileNotFoundError:
        # 没找到文件就发请求下载
        txt = requests.get(URL, timeout=15).text
        # 保存到本地,下次用
        open(SAVE, "w", encoding="utf-8").write(txt)
        return txt


def slice_block(s, i, L, R):
    """从位置i开始找成对的括号(比如{}、[]),返回括号包裹的片段范围
    支持处理字符串里的转义字符,避免误判引号里的括号"""
    l = i  # 记录左括号位置
    dep, ins, esc = 0, False, False  # 深度、是否在字符串内、是否转义
    while i < len(s):
        ch = s[i]
        if ins:  # 如果在字符串里
            if esc:  # 转义符后面的不算
                esc = False
            elif ch == "\\":  # 遇到转义符标记一下
                esc = True
            elif ch == '"':  # 遇到闭合引号,退出字符串状态
                ins = False
        else:  # 不在字符串里
            if ch == '"':  # 遇到引号,进入字符串状态
                ins = True
            elif ch == L:  # 遇到左括号,深度+1
                dep += 1
                if dep == 1:  # 记录最外层左括号位置
                    l = i
            elif ch == R:  # 遇到右括号,深度-1
                dep -= 1
                if dep == 0:  # 深度为0时,找到匹配的右括号
                    return l, i
        i += 1
    # 循环完了都没找到匹配的括号,就报错
    raise ValueError("括号没配平,可能解析错了")


def parse_params_args(js):
    """解析JS里的函数参数和对应的值,把它们做成字典"""
    # 先找到函数定义的位置,比如"(function("后面的参数
    h = js.find("(function(")
    p_end = js.find(")", h + 10)  # 找到参数列表的右括号
    # 提取参数名,按逗号分割并去掉空格
    params = [x.strip() for x in js[h + 10:p_end].split(",") if x.strip()]

    # 找函数体的大括号范围
    b_l = js.find("{", p_end)
    b_l, b_r = slice_block(js, b_l, "{", "}")  # 用自定义函数找配对的大括号

    # 跳过函数体后面可能有的括号和空格,找到实际传入的参数
    i = b_r + 1
    while i < len(js) and js[i].isspace():  # 跳过空格
        i += 1
    if i < len(js) and js[i] == ')':  # 可能有个多余的右括号
        i += 1
    while i < len(js) and js[i].isspace():  # 再跳过空格
        i += 1
    # 找到参数列表的括号范围
    a_l, a_r = slice_block(js, i, "(", ")")
    args_str = js[a_l + 1:a_r]  # 提取括号里的内容

    # 把JS的语法转成Python能认的(比如true→True)
    safe = (args_str.replace("true", "True")
            .replace("false", "False")
            .replace("null", "None")
            .replace("void 0", "None"))
    # 转成Python列表
    values = ast.literal_eval("[" + safe + "]")

    # 把参数名和值对应起来,做成字典返回
    n = min(len(params), len(values))
    return {params[i]: values[i] for i in range(n)}


def slice_return(js):
    """提取JS函数里return后面的对象内容"""
    r = js.find("return")  # 找到return关键字
    l = js.find("{", r)  # 找到return后面的左大括号
    l, r = slice_block(js, l, "{", "}")  # 找到配对的右大括号
    return js[l:r + 1]  # 返回整个对象字符串


def slice_data(ret_obj):
    """从return的对象里提取data数组的内容"""
    k = ret_obj.find("data")  # 找到data字段
    l = ret_obj.find("[", k)  # 找到data后面的左中括号
    l, r = slice_block(js, l, "[", "]")  # 找到配对的右中括号
    return ret_obj[l + 1:r]  # 去掉外层中括号,返回数组内容


def obj_around(pos, text):
    """根据位置pos,找到它所在的整个对象(被{}包裹的部分)"""
    i = pos
    # 从pos往前找最近的左大括号
    while i > 0 and text[i] != '{':
        i -= 1
    # 找到配对的右大括号,返回整个对象字符串
    l, r = slice_block(text, i, "{", "}")
    return text[l:r + 1]


def read_after_colon(obj, key):
    """在对象字符串里,找到key后面的冒号,返回冒号后面的值"""
    p = obj.find(key)  # 找到key的位置
    if p < 0:  # 没找到key就返回None
        return None
    c = obj.find(":", p)  # 找到key后面的冒号
    i = c + 1
    # 跳过冒号后面的空格
    while i < len(obj) and obj[i].isspace():
        i += 1
    if i >= len(obj):  # 超范围了就返回None
        return None

    if obj[i] in "\"'":  # 如果是字符串(用引号括起来的)
        q = obj[i]  # 记录引号类型(单引号或双引号)
        j = i + 1
        esc = False  # 转义标记
        while j < len(obj):
            ch = obj[j]
            if esc:  # 转义符后面的字符不处理
                esc = False
            elif ch == "\\":  # 遇到转义符
                esc = True
            elif ch == q:  # 遇到闭合引号,返回中间的内容
                return obj[i + 1:j]
            j += 1
        return None  # 没找到闭合引号
    else:  # 不是字符串(可能是数字或变量名)
        j = i
        # 找到值的结束位置(遇到逗号、括号或空格)
        while j < len(obj) and obj[j] not in ",}\r\n\t ":
            j += 1
        return obj[i:j]  # 返回值


def resolve(token, mapping):
    """把变量名换成实际的值,比如mapping里有'a':100,就把token'a'换成100"""
    if token is None:
        return ""
    # 从映射表里找,找不到就返回原来的token
    val = mapping.get(token, token)
    return str(val)


def is_number(s):
    """判断一个字符串是不是数字"""
    try:
        float(s)
        return True
    except:
        return False  # 转不成数字就返回False


def main():
    # 获取JS文件内容
    js = fetch_text()
    # 按要求用一下BeautifulSoup(虽然这里没实际解析网页)
    _ = BeautifulSoup("<html></html>", "html.parser")
    # 解析参数映射表(变量名→实际值)
    mp = parse_params_args(js)
    # 提取数据部分的字符串
    data_txt = slice_data(slice_return(js))

    rows, seen = [], set()  # rows存结果,seen去重
    idx = 0  # 记录当前查找位置
    while True:
        # 找包含学校名称的位置(univNameCn是关键词)
        pos = data_txt.find("univNameCn", idx)
        if pos == -1:  # 找不到了就退出循环
            break
        # 提取这个学校的整个数据对象
        obj = obj_around(pos, data_txt)

        # 提取学校名称
        name = read_after_colon(obj, "univNameCn")
        # 提取分数(注意分数可能是变量,需要映射)
        score_tok = read_after_colon(obj, "score")
        score = resolve(score_tok, mp)
        # 如果分数不是数字,就跳过这条数据
        if not is_number(score):
            idx = pos + 10  # 从后面继续找
            continue

        # 提取排名、省份、学校类型(可能是变量,需要映射)
        rank_tok = read_after_colon(obj, "ranking")
        prov_tok = read_after_colon(obj, "province")
        cate_tok = read_after_colon(obj, "univCategory")

        # 把变量换成实际值
        rank = resolve(rank_tok, mp)
        prov = resolve(prov_tok, mp)
        cate = resolve(cate_tok, mp)

        # 把排名转成数字,方便排序
        try:
            r = float(rank)
        except:
            r = 1e9  # 转不成数字的排到最后

        # 去重:用(排名,学校名)作为唯一标识
        key = (r, name)
        if key not in seen:
            seen.add(key)
            rows.append((r, name, prov, cate, score))

        idx = pos + 10  # 继续找下一个学校

    # 按排名排序
    rows.sort(key=lambda x: x[0])
    # 打印表头
    print("排名\t学校名称\t省市\t学校类型\t总分")
    # 打印每条数据
    for r, n, p, c, s in rows:
        # 排名是整数的话就转成整数显示,不然保持原样
        r_out = int(r) if abs(r - int(r)) < 1e-9 else r
        print(f"{r_out}\t{n}\t{p}\t{c}\t{s}")


# 运行主函数
if __name__ == "__main__":
    main()

关键代码解释

1)import requests:用于向软科排名的 JS 数据地址发送网络请求,下载包含学校排名信息的原始数据文件。
2)import ast:将 JS 语法格式的数据(如 true/false/null)转换为 Python 可识别的格式(True/False/None),实现数据类型兼容。
3)import BeautifulSoup:按作业要求引入该库,虽未实际用于 HTML 解析,但满足使用要求。
4)URL = "https://www.shanghairanking.cn/...":目标数据地址,存储软科 2021 年学校排名的 JS 格式数据。
5)SAVE = "payload_202111.js":本地保存文件名,用于缓存下载的 JS 数据,避免重复网络请求。
6)fetch_text():实现本地缓存逻辑,优先读取本地文件,文件不存在时才下载并保存。
7)slice_block(s, i, L, R):核心括号匹配函数,从指定位置开始查找成对括号({}、[]),处理字符串转义避免误判,返回括号包裹的内容范围。
8)parse_params_args(js):解析 JS 函数的参数名与对应值,转换 JS 语法为 Python 格式,生成变量 - 真值的映射字典。
9)slice_return(js):定位 JS 函数中 return 关键字后的对象,提取该对象的完整字符串({} 包裹部分)。
10)slice_data(ret_obj):从 return 的对象中,筛选出 “data” 字段对应的数组内容,去掉外层中括号。
11)obj_around(pos, text):根据关键词(如学校名)的位置,反向查找最近的左大括号,定位其所在的完整数据对象。
12)read_after_colon(obj, key):在数据对象中找到指定关键词(如 “univNameCn”“score”),提取关键词后冒号对应的数值或字符串。
13)resolve(token, mapping):通过映射字典,将数据中的变量名替换为实际数值(如将 “a” 替换为具体分数)。
14)is_number(s):判断字符串是否为数字,用于筛选有效排名和分数数据。
15)main():串联所有步骤,下载解析数据、提取学校名称 / 排名 / 省市 / 类型 / 分数,去重后按排名排序,最终格式化打印结果。

运行结果

--- 显示数据库中存储的前 10 条数据 ---
排名    学校             省市          类型          总分       
------------------------------------------------------
1     清华大学           北京          综合          969.2     
2     北京大学           北京          综合          855.3     
3     浙江大学           浙江          综合          768.7     
4     上海交通大学         上海          综合          723.4     
5     南京大学           江苏          综合          654.8     
6     复旦大学           上海          综合          649.7     
7     中国科学技术大学     安徽          理工          577.0     
8     华中科技大学         湖北          综合          574.3     
9     武汉大学           湖北          综合          567.9     
10    西安交通大学         陕西          综合          537.9     

心得体会

完成这次软科排名爬虫作业,我学会了解析 JS 文件提取数据,掌握了括号匹配、JS 与 Python 数据转换技巧。缓存和去重排序的实现,让我明白爬虫要兼顾效率与准确,也提升了我的逻辑思维和问题解决能力。

posted @ 2025-11-11 21:37  102302131陈宇新  阅读(7)  评论(0)    收藏  举报