当前位置:首页 > 休闲

抓取网站数据

去年冬天,网站我帮一个做二手乐器生意的数据朋友写了个小脚本。他每天要手动翻二十多个琴行的网站网站,把新上架的数据吉他型号和价格抄进Excel。干了两周他受不了了,网站问我能不能让电脑自己干这事。数据我花了一个下午,网站用Python的数据requests和BeautifulSoup写了个抓取程序,三十行代码,网站把他两小时的数据工作压到了三秒。

抓网站数据这件事,网站说穿了就是数据三件事:拿到网页、找到数据、网站存下来。数据但每一件都有坑。网站

拿网页最简单的方式是直接请求URL。Python里requests.get(url)一行就完事。但很多网站会检查你的身份——没有User-Agent头,服务器直接返回403。我第一次跑朋友的脚本就撞上这个,二十个网站有七个拒绝连接。加上浏览器标识之后,只剩两个还在拦。这两个用的是Cloudflare的反爬,普通请求过不去,得换Selenium模拟真实浏览器。代价是速度慢十倍,内存吃掉好几百兆。值不值得,看你要的数据有多重要。

拿到HTML之后才是真正的麻烦。网页结构千变万化,有的用干净的class命名,比如<div class="product-price">2999</div>,用CSS选择器一抓一个准。有的网站偏要把价格塞进<span id="price_1x9f2">这种随机ID里,今天抓到的选择器明天就失效。我朋友的一个供应商网站就是这样,每两周改一次class名。后来我改用正则表达式直接匹配价格数字的模式,虽然粗暴,但稳定了三个月没出问题。

还有更阴的——数据根本不在HTML里。页面加载完,JavaScript再发一个XHR请求去拿JSON数据。你请求原始HTML,看到的只有空壳。这种情况得打开浏览器开发者工具,切到Network面板,找到那个返回数据的接口,直接请求API地址。我遇到过最离谱的一个站点,接口返回的数据是Base64编码的,解码之后还要再解一层JSON。写的时候骂骂咧咧,跑通之后还挺有成就感。

存数据没什么好说的,CSV最省事,要查询就用SQLite。但有个细节容易忽略:编码。中文网站经常用GBK,你按UTF-8读就是乱码。response.encoding = 'gbk'这行不加,抓下来的商品名全是问号。

频率控制是另一个必须考虑的事。你一秒发十个请求,对方服务器管理员不是瞎子。轻则封IP,重则发律师函。我一般设time.sleep(1),模拟人类翻页的节奏。真要抓大量数据,挂代理池轮换IP,但那是另一个话题了。

最后说句实在的:抓数据之前先看robots.txt,再看网站服务条款。有些数据是公开的,抓了没事;有些涉及个人隐私或商业机密,抓了就是给自己找麻烦。技术本身中立,用的人得有点分寸。

分享到: