01|故事开局:当手动复制遇到“滑不到底”的页面
2025 年 3 月,杭州滨江。
运营妹子阿 May 把 MacBook 转过来:“这家金冠微店每天上新 50 款,价格一天三变,我滑到 300 条就闪退,再滑手就要废了。”
我瞄了眼地址栏——
https://weidian.com/?userid=123456789
经典的“店铺首页 + 动态加载”套路。
于是,我打开 VS Code,敲下第一行 import requests。
那一刻,柠檬芋圆的味道,已经在我嘴里爆浆。
02|技术选型:为什么放弃 Selenium,只用 Requests+BeautifulSoup?
方案 | 速度 | 反爬难度 | 结论 |
---|---|---|---|
Selenium | 慢 | 低 | 适合 demo,不适合夜宵 |
Requests+BS4 | 快 | 中 | 够轻、够快、够稳 |
Pyppeteer | 快 | 高 | 杀鸡焉用牛刀 微店 PC 端列表页其实偷偷留了一个静态 HTML 兜底,只要带对 Cookie,就能直接拿到商品块,无需浏览器渲染。 于是,我拍了拍阿 May 的肩膀: “柠檬芋圆等会儿再点,我先给你跑 1 800 条数据,3 分钟见。” |
03|30 行核心代码:让微店“裸奔”
Python
import requests, csv, time, random
from bs4 import BeautifulSoup
from urllib.parse import urljoin
SHOP_ID = '123456789' # ① 目标店铺 ID
COOKIES = {'wdtoken': '抓包所得'} # ② 登录后 F12 抄
HEADERS = {
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64)',
'Referer': f'https://weidian.com/?userid={SHOP_ID}'
}
def crawl_page(page=1):
"""拉取一页 48 件商品"""
url = f'https://weidian.com/user/{SHOP_ID}/items'
params = {'p': page, 'type': 1}
res = requests.get(url, headers=HEADERS, cookies=COOKIES, params=params, timeout=10)
res.raise_for_status()
return res.text
def parse(html):
"""解析出商品 4 件套"""
soup = BeautifulSoup(html, 'lxml')
for div in soup.select('.item-root'):
yield {
'title': div.select_one('.item-title').text.strip(),
'price': div.select_one('.item-price').text.strip(),
'sales': div.select_one('.item-sales').text.strip(), # 已售 x 件
'link' : urljoin('https://weidian.com', div.a['href']),
}
def main():
with open('weidian.csv', 'w', newline='', encoding='utf-8-sig') as f:
writer = None
for p in range(1, 40): # ③ 保守翻 40 页
print(f'[+] 正在偷看第 {p} 页')
html = crawl_page(p)
for prod in parse(html):
if writer is None:
writer = csv.DictWriter(f, fieldnames=prod.keys())
writer.writeheader()
writer.writerow(prod)
time.sleep(random.uniform(1, 2)) # ④ 绅士限速
if __name__ == '__main__':
main()
代码跑起来的样子:
https://miro.medium.com/max/640/1*0Z8Z7dXa3Y5fFcXkPwXJkA.gif
(GIF 仅示意,非真实截图)
3 分钟后,同目录下多出一个 1 800 行的 weidian.csv:
title | price | sales | link |
---|---|---|---|
韩国东大门同款毛绒渔夫帽 | ¥39.9 | 已售 2.3k | https://weidian.com/item.html?itemID=xxx 阿 May 直接 Excel 透视表,把价格段、销量分布、上新节奏一次性拉了出来。 她抬头看我,眼神像发现新大陆: “原来技术可以这么性感?” |
04|进阶:把详情页“掏空”,再薅 5 个字段
列表页只能望梅止渴,真正的战场在详情页:
- 主图 9 张
- SKU 库存
- 图文详情 HTML
- 上架时间
- 运费模板
- 微店详情页接口同样留了静态口子:
GET https://weidian.com/item.html?itemID=xxxx
只要带对 Cookie,返回就是完整 HTML,图片懒加载链接直接躺在 img data-original 里。 - 我顺手写了一个“详情页补全函数”:
Python
def detail(url):
html = requests.get(url, headers=HEADERS, cookies=COOKIES, timeout=10).text
s = BeautifulSoup(html, 'lxml')
return {
'images': [img['data-original'] for img in s.select('.slider-item img')],
'desc' : s.select_one('.detail-txt').text.strip()[:200], # 前 200 字描述
'sku' : [i.text for i in s.select('.sku-name')],
'postage': s.select_one('.postage-txt').text.strip(),
'added' : s.select_one('.added-time').text.strip() # 上架时间
}
在 main() 里每写完一行列表,就同步去拉详情,数据维度瞬间从 4 列扩到 10+ 列。
阿 May 把文件拖到 Power BI,拖拽出一张“上架时间-销量”象限图,指着右上角 quadrant 说:
“这些就是潜力爆款,明天让采购去谈供应链!”
05|反爬锦囊:让蜘蛛学会“绅士步”
微店反爬三板斧:
- 同一 IP 连续 200 次请求 → 弹 403
- 请求缺 Referer / Cookie → 重定向登录
- 流量异常 → 滑块验证码
- 我的对策:
- 免费代理池 https://github.com/fate0/proxylist + requests 的 proxies 参数
- 每 50 页换一次 UA,Referer 全程带店铺首页
- 随机 sleep 1~2 s,偶尔“人性化”停 5 s
- 把 Cookie 的 wdtoken 做成环境变量,30 分钟热更新一次
- 跑了一周,IP 没被封,数据每天增量 200+ 条, Lemon Yakult 也如约到账 10 杯。
06|数据落地:MySQL+Redis,让报表自动“长”出来
CSV 只是前菜,真正的仪式感是自动化数据仓库:
- 爬虫 → MySQL 替换插入(唯一索引 itemID)
- 每日增量 → Redis 队列 推给 BI 服务
- 凌晨 3 点 Airflow 调度 → 自动刷宽表 → 企业微信推送“昨日竞品上新 47 款,涨价 12 款”
- 阿 May 再也不用熬夜,她现在在健身房练马甲线,偶尔给我发微信:
“报表已阅,今天继续躺赢。”
07|法律与道德:先问能不能爬,再问怎么爬
- 只爬公开页面数据,不碰用户隐私、订单接口
- 遵循 robots.txt(微店目前未禁止 user-agent: *)
- 合理限速,单 IP QPS < 1
- 数据仅内部竞品分析,不商用外泄、不二次贩卖
- 技术是把刀,握刀的人决定它是厨具还是凶器。
愿我们都做温柔的数字矿工,而不是粗暴的数据海盗。
08|尾声:当柠檬芋圆变成美金,代码就有了温度
一个月后,阿 May 团队靠这份“竞品数据库”:
- 提前 7 天预判涨价,锁货 3 000 件
- 找到 2 家低 8% 价格的同源工厂
- 单款毛利 +22%,净利润 6.3 万人民币
- 她给我发了一个 66.66 的红包,备注:
“柠檬芋圆可以融化,数据不会。
愿我们都能用技术,让熬夜的人早点回家。”
(完)
附录:一键运行环境
bash
# 1. 克隆示例仓库(含完整代码)
git clone https://github.com/yourname/weidian-spider-demo.git
cd weidian-spider-demo
# 2. 安装依赖
pip install requests beautifulsoup4 lxml pandas
# 3. 填入 Cookie & ShopID
vim config.py
# 4. 启动
python spider.py
祝爬得开心,喝得自由。