做爬虫踩过的坑,记一下

2026-06-12 19:07

做爬虫踩过的坑,记一下



前阵子接了个电商价格监控的活,需求不复杂:定时抓某平台商品价格和库存。但这家的反爬有点东西,踩了几个坑,记下来免得忘。



============================================================

一、别省请求头

============================================================



很多人觉得加个 UA 就完事了。这家会静默检查请求头完整性。



Resync 在《Bot Detection 101》里提过:现代反爬不只是看 UA,而是看整个 TLS 指纹和 HTTP 头的组合偏差。浏览器发出来的头是什么样,你就得是什么样。少一个 Sec-Ch-Ua,返回的就是空白页——不报错,不弹验证码,就是空。这种"什么都不说"的反爬反而最难定位。



session = requests.Session()

session.headers.update({

"User-Agent": "...",

"Accept": "text/html,application/xhtml+xml,"

"application/xml;q=0.9,*/*;q=0.8",

"Accept-Language": "zh-CN,zh;q=0.9",

"Accept-Encoding": "gzip, deflate, br",

"Sec-Ch-Ua": "\"Chromium\";v=\"124\"",

"Sec-Ch-Ua-Platform": "\"Windows\"",

})



============================================================

二、JS 生成的 Cookie

============================================================



首次访问页面会用 JS 在本地跑一段指纹逻辑,生成一个 cookie。不带这个 cookie 的话,后面所有请求都给你甩验证码。



思路:Playwright 开个 headless 浏览器,等 JS 跑完,把 cookie 倒出来给 requests 用。有效期两三个小时,定时刷新就行。



from playwright.sync_api import sync_playwright



with sync_playwright() as p:

browser = p.chromium.launch(headless=True)

page = browser.new_page()

page.goto("https://目标站.com",

wait_until="networkidle")

cookies = page.context.cookies()

browser.close()



============================================================

三、参数签名——卡最久的地方

============================================================



搜索接口有个 sign 参数,32 位小写 hex,一看就是 MD5。但原文是什么?



翻压缩 JS 找到加密那段:



var sign = md5(JSON.stringify(params)

+ "&key=" + _0x3f2a)



_0x3f2a 往回追,发现是从一个配置接口返回的。所以流程是:先调配置接口拿 key → 组装参数 → md5 → 带 sign 发请求。



Python 复现的时候有个细节卡了很久:



import hashlib

import json



def build_sign(params: dict, secret_key: str) -> str:

raw = (json.dumps(params, separators=(",", ":"))

+ "&key=" + secret_key)

return hashlib.md5(raw.encode()).hexdigest()



注意 separators=(",", ":")。JS 的 JSON.stringify 默认不带空格,Python 的 json.dumps 默认带。两边算出来的 sign 不一样,排查了好久。



Intoli 的《The State of Web Scraping》总结过:爬虫工程大部分时间花在逆向和对抗上,真正写采集逻辑的代码反而是少数。确实是这样。



============================================================

四、频率和假数据

============================================================



这家单 IP 每分钟大概 30 次请求到顶。超了不封你,给你假数据——价格全显示 0,库存全显示有货。比直接封更恶心,因为你不会立刻发现。



import time

import random



def safe_request(url, params):

time.sleep(2 + random.uniform(0, 1.5))

resp = session.get(url, params=params)

if all(item["price"] == 0

for item in resp.json()["items"]):

raise ValueError("疑似被风控,数据异常")

return resp.json()



Cloudflare 2024 年的 bot management 报告提到:越来越多的站点从"硬阻断"转向"软对抗"——给你假数据或者降级数据,而不是直接弹验证码。所以爬虫必须自己做数据校验。



============================================================

五、总结

============================================================



请求头校验 → 浏览器发什么你发什么

JS生成Cookie → Playwright 预热后导出

参数签名 → 逆向 JS 再用 Python 复现

频率限制 → 随机延时加代理池

假数据 → 自己加数据校验



写爬虫最大的感受:代码本身不难,难的是搞清楚对方到底用了什么手段。很多坑不在技术上,在你能不能对着 Network 面板,一笔一笔把完整请求链路还原出来。



- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -



目前接一些爬虫、数据采集的私活,有电商数据、价格监控、批量采集需求的可以聊聊。



引用:

Resync —— Bot Detection 101

Intoli —— The State of Web Scraping

Cloudflare —— 2024 Bot Management Report

浏览 1
点赞
评论
收藏
分享

手机扫一扫分享

分享
举报
评论
图片
表情
推荐
点赞
评论
收藏
分享

手机扫一扫分享

分享
举报