打开网易新闻 查看精彩图片

本地测试200条数据零失误,部署到服务器后一夜归零。这不是代码bug,是程序员最容易踩的「环境幻觉」——你的笔记本和服务器,在目标网站眼里完全是两个物种。

周五晚上的自信,周六早晨的403

Scott Reno上周写了个产品数据爬虫。本地用Playwright跑通,顺手抓了200条,没报错没封IP,一切丝滑。他心想这稳了,周五晚上丢到VPS(虚拟专用服务器)上设个定时任务,准备周末躺平。

周六早晨开日志,满屏403 Forbidden。零条数据入库。

问题出在哪?Reno排查后发现,目标网站只查了一个字段:User-Agent(用户代理标识)。他的笔记本因为全局配置了Playwright,发出去的请求带着正常浏览器标识;而服务器是全新Ubuntu,Python的requests库默认亮明身份——

python-requests/2.31.0

打开网易新闻 查看精彩图片

相当于敲门时说「我是来偷数据的机器人」。网站秒拒。

三行代码救场,但教训不止于此

修复很简单:手动塞一个浏览器User-Agent进请求头。Reno的代码变成——

headers = { 'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36...' }

200响应码回来了。但这件事暴露了一个更隐蔽的坑:很多反爬策略不是防技术,是防「不像人」。

Reno在复盘里列了另外两个常见检查点。Referer(来源页面标识):有些网站要求看到你从哪个页面跳过来,直接调API会被拦。Accept系列头部:真实浏览器会声明自己接受什么格式、什么语言、什么压缩方式,裸奔的爬虫往往省略这些「社交礼仪」。

打开网易新闻 查看精彩图片

最便宜的防御,往往最有效

最便宜的防御,往往最有效

User-Agent检查堪称反爬界的「稻草人」——成本低、易绕过,但能挡住80%的粗心爬虫。对网站来说,这是性价比最高的过滤层;对开发者来说,这是最容易忽视的「环境差异」。

Reno的遭遇之所以典型,是因为它完美复刻了「开发-部署」断层:本地环境往往带着各种历史配置,而生产环境是白纸一张。你以为是同一套代码,实际发出的HTTP请求指纹完全不同。

他最后加了一条建议:永远检查response.status_code。被拦时网站可能返回HTML错误页,强行当JSON解析只会得到一堆乱码。先确认活着,再谈吃饭。

这件事在Dev.to(开发者社区)收获大量共鸣。有评论说自己在Docker容器里踩过同样的坑,有人吐槽某些云服务商的默认User-Agent更夸张——直接带服务商名字。最扎心的一条:「我花了三小时调试代理IP,最后发现是User-Agent忘了改。」

你的爬虫最近一次被拦,是从哪一步开始排查的?