去年帮朋友抓取某二手房平台的自网站获挂牌数据,打开开发者工具一看,取外房源列表藏在XHR请求里,部数返回的自网站获是JSON。直接请求那个接口,取外加个User-Agent,部数数据就下来了。自网站获整个过程不到二十分钟。取外但换一个网站,部数同样的自网站获思路可能耗你一整天——这不是夸张,是取外常态。
从网站获取外部数据,部数本质上就两条路:让程序替你打开网页,自网站获再把你要的取外东西从里面挑出来。听起来简单,部数麻烦全在细节里。
用Python的requests发一个GET请求,这是最朴素的起点。但服务器不是吃素的。它看你的请求头里没有User-Agent,直接返回403。你补上UA,它又检查Referer,看你是不是从站内跳转过来的。再往下,Cookie、Token、签名参数,一层一层往上叠。
我见过一个电商网站,搜索接口带了一个sign参数,由时间戳、关键词和一段密钥拼接后做MD5。密钥藏在混淆过的JS文件里,格式化之后三千多行。这种就得动用Pyppeteer或者Playwright这类工具,让真实浏览器去执行JS,你只管拿渲染完的结果。代价是速度慢十倍不止,内存也吃得厉害。
所以每次动手之前,先打开Network面板看一眼:数据是直接嵌在HTML里,还是异步加载的?如果是后者,接口有没有加密参数?这一步花五分钟,能省后面五小时。
拿到HTML之后,新手容易犯的一个错误是用正则表达式去匹配内容。<div class="price">.*?</div>这种写法,页面结构稍微一变就全废。正经做法是用解析库。Python这边,lxml配合XPath是速度最快的组合,BeautifulSoup容错性好但慢一些。如果你要提取的是结构化数据,比如表格或列表,pandas.read_html()有时候能一行搞定。
JSON接口就更省事了,response.json()直接转成字典,按路径取值就行。但要注意有些接口返回的JSON里嵌套了HTML字符串,那就得二次解析。
请求频率高了,IP会被封。最简单的办法是加time.sleep(),但到底睡多久,每个站不一样。有的站一秒五次没事,有的站一分钟十次就给你弹验证码。我一般先用低频率试探,观察响应状态码的变化。
代理池是另一个方案。免费代理基本不能用,十個里九个超时。付费代理按量计费,跑批量任务的时候成本得算清楚。还有一个容易被忽略的点:有些网站封的是请求头指纹,不是IP。这时候换代理没用,得换浏览器指纹或者用无头浏览器模拟真实环境。
验证码是最后的防线。简单的图形验证码可以用ddddocr这类库识别,准确率还行。滑块验证码就麻烦了,要么接打码平台,要么用undetected-chromedriver这类工具绕过检测。但说实话,到了这一步,你得掂量一下这个数据的获取成本是否值得。
技术上行得通,不代表可以随便干。robots.txt不是法律,但它是网站运营者的明确意愿表达。绕过登录墙抓取非公开数据,在国内可能触及《反不正当竞争法》和《个人信息保护法》。2021年有公司因为抓取某平台用户评论被起诉,法院判赔百万。公开数据和公开接口是相对安全的区域,但批量抓取、频繁请求、商业用途,这三个条件叠加起来,风险就上来了。
我的习惯是:只抓页面正常展示给未登录用户的内容,控制频率不给对方服务器造成负担,抓来的数据自己分析用,不转卖不公开。这条线不一定适用于所有人,但至少能让你晚上睡得踏实点。
工具在变,网站的反爬策略也在变。今天能用的方法,下个月可能就失效了。保持动手试的习惯,比收藏一堆教程管用。