翻到两年前写的 Python 爬虫代码,那会儿为了爬 B 站电影排行,折腾请求头、正则匹配,现在重新打开,连带着回忆和新感悟一起涌上来,记录下这段 “考古” 过程~

一、旧代码回顾:那时的思路与实现
import requests
import re
url = 'https://api.bilibili.com/pgc/season/rank/web/list?day=3&season_type=2'
headers = {
'user-agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/116.0.0.0 Safari/537.36 Edg/116.0.0.0',
'Referer': 'https://www.bilibili.com/popular/rank/movie/?from_spmid=666.7.heatlist.more'
}
res = requests.get(url, headers=headers)
# 用正则提取电影名和链接
电影名 = re.findall('"title":"(.*?)"', res.text)
电影链接 = re.findall('"url":"(.*?)"', res.text)
movie_dict = {}
for 电影名, 电影链接 in zip(电影名, 电影链接):
movie_dict[电影名] = 电影链接
for 电影名, 电影链接 in movie_dict.items():
print(f"{电影名}:{电影链接}")
当时的思路:
- 直接用
requests
硬刚接口,靠User - Agent
和Referer
伪装浏览器; - 正则表达式当 “万能提取器”,不管结构直接挖字符串;
- 用
zip
简单配对数据,功能实现就满足,完全没考虑扩展性。
二、现在看旧代码:槽点与成长
(一)被时代淘汰的 “野路子”
1.正则硬刚 JSON:
现在才懂,API 返回明明是 JSON 数据,却用正则暴力解析,既易错(结构变一点就失效)又低效。当时要是学 res.json()
直接解析字典,代码能简洁一半:
data = res.json()
电影名 = [item['title'] for item in data['result']]
电影链接 = [item['url'] for item in data['result']]
(不过也理解,当时刚接触爬虫,能提取到数据就很兴奋,顾不上优雅…)
2.反爬意识太 naive:
两年前 B 站反爬没现在严格,靠简单请求头就能过。放到现在,这种写法大概率被拦截 —— 需要加 Cookie、处理动态参数,甚至面对验证码、JS 混淆。
3.异常处理等于零:
代码里没写 try - except
,网络波动、接口改结构直接报错崩溃。现在写代码,会习惯性加防御:
try:
res = requests.get(url, headers=headers, timeout=10)
res.raise_for_status() # 非 200 状态直接抛异常
except requests.RequestException as e:
print(f"请求失败:{e}")
三、重启项目:优化与拓展
(一)重构代码:更规范、更健壮
import requests
def get_bilibili_movies():
url = 'https://api.bilibili.com/pgc/season/rank/web/list?day=3&season_type=2'
headers = {
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/126.0.0.0 Safari/537.36',
'Referer': 'https://www.bilibili.com/'
}
try:
res = requests.get(url, headers=headers, timeout=15)
res.raise_for_status()
data = res.json()
# 直接解析 JSON 数据
movies = []
for item in data.get('result', []):
movies.append({
'title': item.get('title', '无标题'),
'url': item.get('url', '无链接'),
'score': item.get('score', '无评分') # 新增评分字段
})
return movies
except requests.RequestException as e:
print(f"获取数据失败:{e}")
return []
if __name__ == '__main__':
movies = get_bilibili_movies()
for idx, movie in enumerate(movies, start=1):
print(f"【{idx}】{movie['title']} - {movie['score']}\n链接:{movie['url']}\n")
优化点:
- 用 JSON 解析替代正则,更稳定、可读性高;
- 增加异常处理,网络问题不崩溃;
- 扩展数据(如评分),让信息更完整;
(二)功能拓展:从 “能跑” 到 “好用”
1.数据持久化:
以前直接打印,现在可以存成 CSV/Excel:
import csv
with open('b站电影排行.csv', 'w', newline='', encoding='utf-8') as f:
writer = csv.DictWriter(f, fieldnames=['title', 'url', 'score'])
writer.writeheader()
writer.writerows(movies)
2.可视化展示:
用 pandas
或 matplotlib
做简单分析,比如按评分排序、统计高分电影占比,让数据更直观。
3.定时更新 + 通知:
结合 schedule
库定时爬取,用邮件 / 微信推送新上榜电影,真正让代码 “有用” 起来。
四、回忆与成长:两年的意义
看着两年前的代码,想起当时为了调通正则熬夜,为成功爬取到 100 条数据欢呼。现在虽然觉得代码很 “稚嫩”,但正是这些 “野路子”,让我一步步摸到编程的门道。
对比现在,能明显感受到:
- 从 “实现功能” 到 “考虑健壮性、可维护性”;
- 从 “暴力破解” 到 “尊重接口规范、数据结构”;
- 从 “写代码玩” 到 “思考实际价值”。
这两年,代码能力在变,对编程的理解也在变。旧代码像时光胶囊,提醒我:进步就是回头看时,能清晰发现 “以前好傻,但当时真的很勇敢”。
如果你也翻到旧项目,不妨也重构试试,说不定能挖到比代码更珍贵的成长~
(注:爬虫需遵守网站 robots.txt
协议和相关法律法规,本项目仅用于学习交流,合理使用数据哦~)