从爬虫到模型:一个应届生的AI编程初体验
去年秋招拿到offer后,我本以为大四下学期能躺平到入职。结果上周五晚上十点,直属Leader突然在钉钉上@我:“小张,有个紧急需求,下周三前要上线一个竞品价格监控模块,你先搭个原型看看。” 我盯着屏幕愣了三秒——这不就是让我边写爬虫边搞机器学习吗?但谁让我是那个“会点Python”的应届生呢(手动狗头)。
坐标上海,租住在公司隔壁小区,步行十分钟就能到工位。本来想着入职前最后一个月好好打游戏,结果被这个需求拉回了现实。不过也好,正好把之前学的机器学习理论落地一下,毕竟在学校里调参都是用sklearn自带的iris数据集,连真实数据长啥样都不知道。
需求背景:老板想要“智能比价”
事情是这样的:我们团队做的是电商SaaS工具,最近产品经理提了个需求——自动抓取竞品平台的商品价格,然后预测“合理定价区间”。听起来很玄乎,其实就是两个步骤:
- 爬虫:定时抓取京东、拼多多等平台的商品页
- AI编程:用历史价格数据训练模型,预测未来7天的价格波动
产品经理原话是:“用户输入商品ID,系统就能告诉ta现在是不是抄底价”。我当时内心OS:这需求怕不是看了太多AI宣传视频?但转念一想,这不正是练手的好机会吗?
第一步:爬虫不是你想爬,想爬就能爬
先说爬虫部分。我一开始直接用requests+BeautifulSoup硬刚,结果第二天就被反爬机制教做人——京东直接返回{"error": "403 Forbidden"},拼多多更狠,页面全是加密的JS动态渲染。
踩坑记录:
- 用普通User-Agent被秒封IP
- 动态加载的内容根本拿不到
- 商品价格藏在JSON-LD结构化数据里,解析逻辑复杂
后来在GitHub上翻到一个叫selenium-wire的库(感谢开源社区!),配合代理池总算搞定。关键代码如下:
from seleniumwire import webdriver
from fake_useragent import UserAgent
import time
import json
def scrape_jd_price(sku_id):
# 随机User-Agent防检测
ua = UserAgent()
options = webdriver.ChromeOptions()
options.add_argument(f'--user-agent={ua.random}')
options.add_argument('--headless') # 无头模式,省资源
driver = webdriver.Chrome(options=options)
try:
url = f"https://item.jd.com/{sku_id}.html"
driver.get(url)
time.sleep(3) # 等待JS加载
# 从页面源码中提取JSON-LD数据
scripts = driver.find_elements("tag name", "script")
for script in scripts:
if "application/ld+json" in script.get_attribute("type"):
data = json.loads(script.get_attribute("innerHTML"))
price = data.get("offers", {}).get("price", None)
return float(price) if price else None
finally:
driver.quit()
吐槽:运维同事看到我本地跑ChromeDriver差点报警,说“你这进程占了2G内存,服务器要炸了”。后来改成用Docker容器隔离才过关。
第二步:数据有了,但AI模型怎么选?
爬虫跑了一周,攒了5000多条商品价格记录(主要是手机、耳机这类3C产品)。接下来就是重头戏——AI编程。我翻出《机器学习实战》和吴恩达的课,开始纠结用什么算法。
初期方案:线性回归(天真如我)
第一反应是用线性回归,毕竟最简单。假设价格只和时间相关,画个散点图:
| 时间戳 | 价格(元) |
|---|---|
| 1678900000 | 2999 |
| 1678986400 | 2899 |
| ... | ... |
代码三行搞定:
from sklearn.linear_model import LinearRegression
model = LinearRegression()
model.fit(X_train, y_train)
结果?预测误差高达±300元!因为价格根本不是线性变化的——大促前降价、新品发布后老款跳水,这些非线性规律线性模型完全捕捉不到。
转向树模型:XGBoost真香
被现实毒打后,我转向了集成学习。XGBoost在Kaggle比赛里常年霸榜,对特征工程要求低,特别适合我这种新手。关键改进点:
特征工程:不只是时间,还加入了:
- 是否工作日(0/1)
- 距离最近大促天数(双11、618等)
- 历史价格波动率(标准差)
- 竞品平均价格(需要爬多个平台)
处理时间序列:用滑动窗口构造特征,比如用过去7天的价格预测第8天
# 特征构造示例
def create_features(df):
df['day_of_week'] = df['timestamp'].dt.dayofweek
df['is_weekend'] = (df['day_of_week'] >= 5).astype(int)
df['price_7d_avg'] = df['price'].rolling(window=7).mean()
df['price_7d_std'] = df['price'].rolling(window=7).std()
return df.dropna()
- 调参玄学:用GridSearchCV暴力搜索,但发现
max_depth=5和learning_rate=0.1基本够用
最终模型在测试集上MAE(平均绝对误差)降到±85元,对于3000元价位的手机来说,误差<3%,产品经理勉强点头。
模型部署:从Notebook到线上服务
本以为训练完就结束了,结果Leader说:“明天演示,得做成API”。我连夜用Flask搭了个微服务:
from flask import Flask, request, jsonify
import joblib
app = Flask(__name__)
model = joblib.load('price_predictor.pkl')
@app.route('/predict', methods=['POST'])
def predict():
data = request.json
sku_id = data['sku_id']
# 1. 实时爬取当前价格
current_price = scrape_jd_price(sku_id)
# 2. 构造特征(省略细节)
features = build_features(sku_id, current_price)
# 3. 预测
prediction = model.predict([features])
return jsonify({
'predicted_price': float(prediction[0]),
'confidence_interval': [prediction[0]*0.95, prediction[0]*1.05]
})
血泪教训:
- 模型文件用joblib保存,比pickle快3倍
- 爬虫加了缓存,避免重复请求(Redis存2小时)
- 用gunicorn部署,4 worker进程扛住压力测试
上线当天,测试同学疯狂刷接口,QPS飙到200+,服务器CPU瞬间90%。最后加了限流(每IP每分钟10次)才稳住。运维看我的眼神仿佛在说:“应届生真是初生牛犊不怕虎”。
效果对比:不同算法的真实表现
为了说服自己没选错模型,我横向对比了三种算法在相同数据集上的表现:
| 算法 | MAE(元) | 训练时间(s) | 特征工程难度 | 适合场景 |
|---|---|---|---|---|
| 线性回归 | 298 | 0.5 | ⭐ | 趋势简单、噪声少 |
| 随机森林 | 112 | 8.2 | ⭐⭐ | 中等复杂度、可解释性要求高 |
| XGBoost | 85 | 5.7 | ⭐⭐ | 高精度、大数据量 |
注:测试环境为MacBook Pro M1, 16GB RAM
结论很明显:XGBoost在精度和速度上取得了最佳平衡。虽然深度学习(比如LSTM)可能更准,但对我这种单机开发、数据量不大的场景,纯属杀鸡用牛刀。
给新人的建议:别被“AI”两个字吓到
折腾完这个项目,我最大的感悟是:机器学习没那么神秘。它本质就是“用数学方法找规律”,而AI编程的核心能力其实是:
- 数据清洗能力:80%的时间花在处理脏数据上
- 问题定义能力:把业务需求翻译成技术指标(比如“合理价格” → “预测MAE<100元”)
- 工程化思维:模型再准,跑不起来等于零
顺便吐槽下:现在有些教程一上来就讲Transformer、BERT,搞得新人以为不会深度学习就out了。其实工作中,XGBoost + 特征工程 能解决80%的问题。我们组去年所有AI项目,70%都用的传统机器学习。
最后:应届生如何快速上手AI编程?
如果你和我一样是CS专业应届生,想在入职前突击AI技能,我的建议是:
- 别死磕理论:先跑通一个端到端项目(爬虫→训练→部署)
- 善用现成工具:sklearn、XGBoost、LightGBM文档齐全,API友好
- 从小数据开始:用Kaggle的Titanic或House Prices入门,别一上来就想搞CV/NLP
- 重视工程细节:模型保存、API设计、错误处理,这些才是面试加分项
现在我已经把这套代码整理成开源项目(GitHub搜price-predictor-demo),欢迎star。入职前最后两周,我打算用这套框架再做个“租房价格预测”——毕竟在上海,搞懂房价比搞懂算法更重要(笑)。
对了,如果你们公司也在招人,记得内推我啊!(不是)

评论 0