凌晨两点,爬虫我盯着终端里滚动的网页错误日志,第37次请求又超时了。源代目标网站的爬虫反爬虫机制像一道铁闸,把我精心构造的网页请求头全部弹了回来。这时我忽然意识到,源代自己连这个网页最基本的爬虫HTML结构都没见过——我只是在盲目地撞墙。
爬虫的网页第一步从来不是写代码,而是源代先拿到网页源代码。就像你要拆一台机器,爬虫总得先打开外壳看看里面的网页齿轮怎么咬合。我见过太多新手上来就调requests库,源代对着返回的爬虫JSON瞎猜字段,结果页面改版一次就全线崩溃。网页真正的源代老手会先右键点击“查看网页源代码”,花十分钟把HTML从头滚到尾,心里大概有了数,才开始动手。
用Python写这段逻辑其实很直白。核心代码不超过十行:import requests
resp = requests.get(url, headers=headers)
resp.encoding = resp.apparent_encoding
print(resp.text)
但细节藏在headers里。你得把自己伪装成浏览器——User-Agent要带上Chrome的版本号,Referer填上目标网站的首页,有时候还得加上Accept-Language。不然服务器一眼就识破你是爬虫,直接给你返回一个验证码页面。我第一次爬某电商网站时,就因为少了Cookie字段,拿到手的全是登录跳转的JS代码,当时还以为自己写错了URL。
拿到源代码之后,别急着用BeautifulSoup去解析。先肉眼扫一遍。看title标签里写的是什么,看meta描述符是否包含关键信息,看script标签里是不是藏着动态渲染的数据。有一次我爬一个新闻网站,发现正文内容根本不在HTML里,而是被一个叫window.__INITIAL_STATE__的JS变量存着。要不是我多看了两眼源代码,差点就要去用Selenium模拟浏览器,那效率可就差了十万八千里。
网页源代码里藏着许多“不诚实”的地方。有些站点的HTML看起来规规整整,但注释里留着开发者的调试信息,比如<!-- 这里的数据是假的,请勿爬取 -->。这种话不能全信,但也不能完全无视。还有的页面会在CSS里隐藏真实内容,文字颜色设成白色,背景也是白色,肉眼看不见,但源代码里明明白白。爬虫的世界里,源代码就是唯一的事实来源。
记得有个下午,我为了爬一个政府公开数据平台,反复调试了四个小时。最后发现对方把数据塞在了一个iframe里,而iframe的src是动态生成的。我一开始只抓了主页面,自然什么都拿不到。当我用requests又去请求那个iframe地址时,才发现里面的HTML才是真正有价值的。那一刻我靠在椅背上,觉得这就像剥洋葱——最外层的壳看起来完整,但真正的味道在层层包裹的内里。
写爬虫的乐趣在于,每一次抓取都是一次和网站开发者的隔空对话。你在源代码里能看到他们用注释留下的抱怨,能看到他们为了兼容老浏览器写的冗余代码,甚至能通过HTML结构的变化推测出他们最近重构过几次前端。这些信息比任何API文档都来得鲜活。当然,拿到源代码只是开始,后面还有清洗数据、处理动态加载、应对IP封锁这些麻烦事。但第一步永远是笨拙地、耐心地,把那段HTML原原本本地拿在手里,像读一封信那样读它。