数据采集实践第二次作业—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 数据转换技巧。缓存和去重排序的实现,让我明白爬虫要兼顾效率与准确,也提升了我的逻辑思维和问题解决能力。

浙公网安备 33010602011771号