最近寒假在家学习Node.js开发,光看书或者跟着敲代码还不够,得找一点有趣的事情来玩一玩,于是我决定写一个Node爬虫,爬取一些有意思或者说是有用的数据。这个决定只与我的兴趣有关,与Python或者Node或者Java等等谁更适合写爬虫无关,与爬取多少数据无关,与爬取的对象无关。

1 确定爬取目标

在写Node爬虫之前,我们先要确定爬取的网站目标。

这个目标的选择有一定的标准,首先得具有可行性,必须能够爬取到这个网站上的数据,否则一切都是空谈;其次,网站上数据的真实性或者数据量必须满足你的需求;最后,网站的响应速度也是我们需要考虑的一个因素。

基于这些标准,我选择了智联招聘网站作为我的爬取目标,爬取的数据是全国主要城市的主要软件工作岗位的招聘数据。

2 写一个Node爬虫

2.1 探寻网站风格

确定爬取目标之后,我们就可以着手写Node爬虫了。由于每一个网站的代码风格不同,我们针对不同网站所写的爬虫也会不同。

在写爬虫之前,我们需要先查看一下智联招聘网站的url风格,以及代码风格。

在智联招聘的首页,我们可以发现一个搜索栏,填入工作和地点之后,我们就可以点击搜索查看对应招聘信息,这时候我们可以探究一下智联招聘url中暗藏的秘密。当我选择珠海城市的Web开发岗位的时候,我的url是下图这样的:

多试几次,或者把鼠标放在下图中的链接上。

我们就可以发现url中参数的意义所在。

其他参数我们不用管,我们只需要知道sj是岗位代码,p是当前数据页码(搜索结果可能有很多页,智联招聘是每页60条记录),jl是城市就可以了。知道这两个参数的意义之后,我们就可以通过组合url来获取不同城市不同岗位的招聘信息了。

2.2 解析HTML文本

在Node中组合url,然后通过http模块的get方法,我们可以获取到来自智联招聘网站的响应。

function getData(pageNo, job, jobLocation, jobsCount){
var url = encodeURI(`http://sou.zhaopin.com/jobs/searchresult.ashx?bj=160000&sj=${variables.jobs[job]}&in=160400&jl=${jobLocation}&p=${pageNo}&isadv=0`);
var jobs = [];
console.log(`${job}-${jobLocation}...`);
return new Promise((resolve, reject)=>{
try{
http.get(url, (res)=>{

不难发现我们得到的响应是一个html文件,我们可以通过解析html文本来获取其中的数据信息。最直接的方法是通过RegExp,但是获取的信息较多时会比较麻烦。

我选择的是通过第三方库——cheerio,来解析HTML文本。这个库使用起来简单方便,能够让你在V8引擎中通过jQuery操作DOM节点的方式解析HTML文本信息。

$('table.newlist').each((k, v)=>{
var job = {};
job.company = $('td.gsmc', v).text();
job.salary = $('td.zwyx', v).text();
job.name = String($('td.zwmc>div', v).text()).replace(/\s/g, '');
job.location = jobLocation;
if(job.company !== '' && job.salary !== '面议'){
jobs.push(job);
}
});

上面这段代码就是我通过cheerio解析HTML文本的代码。

在同时发起多个请求时,有可能会漏掉一些请求,我认为是并发太多导致服务器没有响应,应该通过setTimeout函数延迟一下多个请求。这一点在我将处理后的数据存到LeanCloud平台时得到了验证。

3 存储爬取到的数据

我选择的是MongoDB作为我的后台数据库,因为MongoDB以文档形式存储数据,数据格式是BSON,与Node.js的亲和性很好。

MongoDB操作简单,性能很高,能够满足我的开发需求。

在官网下载MongoDB的Windows安装包之后(需要科学上网),在Windows平台安装,最好不要安装自带的可视化工具,因为会消耗相当长的时间,我们可以选择Robo 3T作为替代品。其他安装过程可以自行百度。

我们在Node中使用MongoDB需要先通过MongoDB Driver,我选择的是mongodb。

通过

npm install mongodb --save

就可以安装,然后在Node代码中通过

require('mongodb')

引入。

存储代码:

const MongoClient = require('mongodb').MongoClient;
//将数据写入数据库
function writeDB(type, realJobs){
MongoClient.connect('mongodb://localhost:27017', (e, db)=>{
assert.ifError(e);
var jobs = db.db('jobs');
var collection = jobs.collection('jobs');
realJobs.forEach((job)=>{
collection.insert(Object.assign({}, job, { type }));
});
db.close();
});
}

4 通过Node解析数据

通过爬虫获取的数据还只是原始数据,我需要通过Node将其转化为我需要的数据,比如对深圳的Web前端开发岗位薪资取平均值。

这一过程简而言之就是将数据从MongoDB中取出来,然后取平均值。处理之后的代码我将它们存到了LeanCloud上,以便于我的前端展示页面调用。

5 前端页面展示

我使用React框架写前端页面,综合React Router插件实现客户端路由,后台数据存储在LeanCloud上,通过LeanCloud的SDK即可在前端页面实现数据查询。

图表的展示我使用echarts插件,这款插件由百度团队开发,使用起来已经不比highcharts差了,性能方面表现感觉很出色。

6 总结

这次开发极大地增强了我的学习兴趣,通过爬取的数据我也对软件行业在各城市的发展有了一定的了解。这一次从后端到前端的开发,让我学到了新的知识,也复习了之前学习过的旧知识,受益匪浅。

文章发表在我的个人博客,欢迎访问!

最新文章

  1. Netty_UDP丢包解决
  2. oracle 11.2.0.4单实例文件系统安装与补丁
  3. 使用Cordova和JQM在ios上需要注意的问题
  4. Struts2入门1 Struts2基础知识
  5. 如何实现在H5里调起高德地图APP?(下)
  6. meta之renderer
  7. C#.web 打开PDF
  8. Linux开机自动挂载存储
  9. 【转】Cygwin访问Windows驱动器
  10. 深度学习多机多卡解决方案-purine
  11. bzoj 1449 [JSOI2009]球队收益(费用拆分,最小费用流)
  12. C#多线程Thread.Join()的详解
  13. Python3 日期和时间
  14. java枚举通俗实例解析
  15. Golang 笔记 1 基础、基本数据类型
  16. [20180608]Wrong Results with IOT, Added Column and Secondary Index.txt
  17. SQLServer 常见SQL笔试题之语句操作题详解
  18. mysql的完整卸载
  19. Tomcat7出现HTTP Status 500 - java.lang.ClassCastException: org.apache.jasper.el.ELContextImpl cannot be cast to org.apache.jasper.el.ELContextImpl的解决
  20. 侵入式单链表的简单实现(cont)

热门文章

  1. 九度oj 1003 A+B 2010年浙江大学计算机及软件工程研究生机试真题
  2. div+css 让一个小div在另一个大div里面 垂直居中
  3. 计算两个NSDate之间,相隔多少秒数
  4. jmeter(1)——环境部署及安装
  5. 判断网站域名是否被GFW(墙)过滤屏蔽了
  6. log4j.properties 基本配置
  7. 铵钮提交事件PostBack之后,一些动态加载的物件丢失
  8. ASP.NET Visual Studio2010 发布Web网站问题详解
  9. [android] 与PHP的session进行交互demo
  10. python6