如何用.NET编写抓取拉勾网信息?
摘要:前几天看到一个.NET Core写成的爬虫,有些莫名的小兴奋,之前一直用集搜客去爬拉勾网的招聘信息,这个傻瓜化工具相当于用HTML模板页去标记DOM节点,然后在浏览器窗口上模拟人的浏览行为同时跟踪节点信息。它有很多好处,但缺点也明显:抓取速
前几天看到一个.NET Core写成的爬虫,有些莫名的小兴奋,之前一直用集搜客去爬拉勾网的招聘信息,这个傻瓜化工具相当于用HTML模板页去标记DOM节点,然后在浏览器窗口上模拟人的浏览行为同时跟踪节点信息。它有很多好处,但缺点也明显:抓取速度慢;数据清洗和转储麻烦;只知其过程,不知其原理,网站改了模板或者要爬取别的网站,重现效率反而不如自己写个程序。
那么就自己实现一个?说干就干!
首先了解需要拉勾网的网页结构。对于搜索结果需要点击控件才能展示分页,不用这么麻烦,查看网络,发现每次点击下一页会向一个地址发出异步POST请求:
URL:https://www.lagou.com/jobs/positionAjax.json?px=new&needAddtionalResult=false
它的请求数据为(以.Net搜索的第2页为例):first=false&pn=2&kd=.NET
显然pn和kd分别传入的是页码和搜索关键词。
再检查它的响应报文,返回的是单页所有的职位信息,格式是JSON:
可以用JavaScriptSerializer类的DeserializeObject方法反序列为字典。
对于职位详情(每个职位的主页),返回的是html,解析html的工具包之前用Html Agility Pack,不过据说AngleSharp性能更优,这次打算换成它。
我马上想到了用Socket做一个客户端程序,先试了一下.NET Core,发现缺很多类库,太麻烦,还是用回.NETFramework,很快碰到了302重定向问题、Https证书问题,线程阻塞等一序列问题,Socket处理起来比较棘手,果断弃之,HttpWebRequest简便,但是 Post请求同样也会发生302错误,伪装普通浏览器的请求头或者给它重定向都解决不了,试了试改换成Get方式发现可以避开所有的问题,不由得开心了起来,一不小心访问得过于频繁,导致如下结果:
这样就能阻止我?你这么难搞,干脆把整站扒下来。
正好手头有个Azure账号没过期,顺便开个虚拟机玩玩。
测试成功后写个正式的程序,我把它叫做拉勾职位采集器,入门级,今后如果用得多或者出现了新的问题还得动手升级它。
按照面向对象的思想,程序就像在不同的车床构造零部件最后再装配成产品,整个过程流水作业。我的基本思路是单个采集器实例采集一组关联关键词(有些关键词可以不作区分,如C#和.Net),存为单个xml文档(也可以存到数据库、Excel、缓存中,我比较习惯于存为xml然后再映射到Excel文档),过程用Log4Net记录日志。
