以前一直听说有爬虫这种东西,稍微看了看资料,貌似不是太复杂。
正好了解过node.js,那就基于它来个简单的爬虫。
1.本次爬虫目标:
从拉钩招聘网站中找出“前端开发”这一类岗位的信息,并作相应页面分析,提取出特定的几个部分如岗位名称、岗位薪资、岗位所属公司、岗位发布日期等。并将抓取到的这些信息,展现出来。
初始拉钩网站上界面信息如下:
2.设计方案:
爬虫,实际上就是通过相应的技术,抓取页面上特定的信息。
这里主要抓取上图所示岗位列表部分相关的具体岗位信息。
首先,抓取,就得先有地址url:
http://www.lagou.com/jobs/list_%E5%89%8D%E7%AB%AF%E5%BC%80%E5%8F%91?kd=%E5%89%8D%E7%AB%AF%E5%BC%80%E5%8F%91&spc=1&pl=&gj=&xl=&yx=&gx=&st=&labelWords=label&lc=&workAddress=&city=%E5%85%A8%E5%9B%BD&requestId=&pn=1
这个链接就是岗位列表的第一页的网页地址。
我们通过对地址的参数部分进行分析,先不管其他选择的参数,只看最后的参数值:pn=1
我们的目的是通过page来各个抓取,所以设置为pn = page;
其次,爬虫要获取特定信息,就需要特定代表的标识符。
这里采用分析页面代码标签值、class值、id值来考虑。
通过Firebug对这一小部分审查元素
分析得出将要获取哪些信息则需要对特定的标识符进行处理。
3.代码编写:
按照预定的方案,考虑到node.js的使用情况,通过其内置http模块进行页面信息的获取,另外再通过cheerio.js模块对DOM的分析,进而转化为json格式的数据,控制台直接输出或者再次将json数据传送回浏览器端显示出来。
(cheerio.js这东西的用法很简单,详情可以自行搜索一下。其中最主要的也就下边这份代码了,其余的跟jQuery的用法差不多。
就是先将页面的数据load进来形成一个特定的数据格式,然后通过类似jq的语法,对数据进行解析处理)
var cheerio = require('cheerio'), $ = cheerio.load('<h2 class="title">Hello world</h2>');$('h2.title').text('Hello there!');$('h2').addClass('welcome');$.html();//=> <h2 class="title welcome">Hello there!</h2>
采用exPRess模块化开发,按要求建立好项目后。进入项目目录,执行npm install安装所需依赖包。如果还不了解express的可以 到这里看看
爬虫需要cheerio.js 所以另外require进来, 所以要另外 npm install cheerio
项目文件很多,为了简单处理,就只修改了其中三个文件。(index.ejs index.js style.CSS )
(1)直接修改routes路由中的index.js文件,这也是最核心的部分。
还是看代码吧,有足够的注释
1 var express = require('express'); 2 var router = express.Router(); 3 var http = require('http'); 4 var cheerio = require('cheerio'); 5 6 /* GET home page. */ 7 router.get('/', function(req, res, next) { 8 res.render('index', { title: '简单nodejs爬虫' }); 9 });10 router.get('/getJobs', function(req, res, next) { // 浏览器端发来get请求11 var page = req.param('page'); //获取get请求中的参数 page12 console.log("page: "+page);13 var Res = res; //保存,防止下边的修改14 //url 获取信息的页面部分地址15 var url = 'http://www.lagou.com/jobs/list_%E5%89%8D%E7%AB%AF%E5%BC%80%E5%8F%91?kd=%E5%89%8D%E7%AB%AF%E5%BC%80%E5%8F%91&spc=1&pl=&gj=&xl=&yx=&gx=&st=&labelWords=label&lc=&workAddress=&city=%E5%85%A8%E5%9B%BD&requestId=&pn=';16 17 http.get(url+page,function(res){ //通过get方法获取对应地址中的页面信息18 var chunks = [];19 var size = 0;20 res.on('data',function(chunk){ //监听事件 传输21 chunks.push(chunk);22 size += chunk.length;23 });24 res.on('end',function(){ //数据传输完25 var data = Buffer.concat(chunks,size); 26 var html = data.toString();27 // console.log(html);28 var $ = cheerio.load(html); //cheerio模块开始处理 DOM处理29 var jobs = [];30 31 var jobs_list = $(".hot_pos li");32 $(".hot_pos>li").each(function(){ //对页面岗位栏信息进行处理 每个岗位对应一个 li ,各标识符到页面进行分析得出33 var job = {};34 job.company = $(this).find(".hot_pos_r div").eq(1).find("a").html(); //公司名35 job.period = $(this).find(".hot_pos_r span").eq(1).html(); //阶段36 job.scale = $(this).find(".hot_pos_r span").eq(2).html(); //规模37 38 job.name = $(this).find(".hot_pos_l a").attr("title"); //岗位名39 job.src = $(this).find(".hot_pos_l a").attr("href"); //岗位链接40 job.city = $(this).find(".hot_pos_l .c9").html(); //岗位所在城市41 job.salary = $(this).find(".hot_pos_l span").eq(1).html(); //薪资42 job.exp = $(this).find(".hot_pos_l span").eq(2).html(); //岗位所需经验43 job.time = $(this).find(".hot_pos_l span").eq(5).html(); //发布时间44 45 console.log(job.name); //控制台输出岗位名46 jobs.push(job); 47 });48 Res.json({ //返回json格式数据给浏览器端49 jobs:jobs50 });51 });52 });53 54 });55 56 module.exports = router;
(2)node.js抓取的核心代码就是上面的部分了。
下一步就是将抓取到的数据展示出来,所以需要另一个页面,将views中的index.ejs模板修改一下
1 <!DOCTYPE html> 2 <html> 3 <head> 4 <title><%= title %></title> 5 <link rel='stylesheet' href='/stylesheets/style.css' /> 6 </head> 7 <body> 8 <h3>【nodejs爬虫】 获取拉勾网招聘岗位--前端开发</h3> 9 <p>初始化完成 ...</p>10 <p><button class="btn" id="btn0" onclick="cheerFetch(1)">点击开始抓取第一页</button></p>11 <div class="container">12 <!--<div class="jobs"> </div>-->13 </div>14 <div class="footer">15 <p class="fetching">数据抓取中 ... 请稍后</p>16 <button class="btn" id="btn1" onclick="cheerFetch(--currentPage)">抓取上一页</button>17 <button class="btn" id="btn2" onclick="cheerFetch(++currentPage)">抓取下一页</button>18 </div>19 <script type="text/javascript" src="Javascripts/jquery.min.js"></script>20 <script type="text/javascript">21 function getData(str){ //获取到的数据有杂乱..需要把前面部分去掉,只需要data(<em>......<em> data)22 if(str){23 return str.slice(str.lastIndexOf(">")+1);24 }25 }26 27 document.getElementById("btn1").style.visibility = "hidden";28 document.getElementById("btn2").style.visibility = "hidden";29 var currentPage = 0; //page初始030 31 function cheerFetch(_page){ //抓取数据处理函数32 if(_page == 1){ 33 currentPage = 1; //开始抓取则更改page34 }35 $(document).AjaxSend(function(event, xhr, settings) { //抓取中...36 $(".fetching").css("display","block");37 });38 $(document).ajaxSuccess(function(event, xhr, settings) { //抓取成功39 $(".fetching").css("display","none");40 });41 $.ajax({ //开始发送ajax请求至路径 /getJobs 进而作页面抓取处理42 data:{page:_page}, //参数 page = _page43 dataType: "json",44 type: "get",45 url: "/getJobs",46 success: function(data){ //收到返回的json数据47 console.log(data);48 var html = "";49 $(".container").empty();50 if(data.jobs.length == 0){ 51 alert("Error2: 未找到数据..");52 return;53 }54 for(var i=0;i<data.jobs.length;i++){ //遍历数据并提取处理55 var job = data.jobs[i];56 html += "<div class='jobs'><p><span >岗位序号:</span> "+((i+1)+15*(currentPage-1))+"</p>"+57 "<p>岗位名称:<a href='"+job.src+"'target='_blank'>"+job.name+"</a></p>"+58 "<p><span >岗位所在公司:</span> "+job.company+"</p>"+59 "<p><span>公司阶段:</span> "+getData(job.period)+"</p>"+60 "<p><span>岗位规模:</span> "+getData(job.scale)+"</p>"+61 "<p><span>岗位所在城市:</span> "+job.city+"</p>"+62 "<p><span>岗位薪资:</span> "+getData(job.salary)+"</p>"+63 "<p><span>岗位最低经验要求:</span> "+getData(job.exp)+"</p>"+64 "<p><span>岗位发布时间:</span> "+getData(job.time)+"</p>"+65 "</div>"66 }67 68 $(".container").append(html); //展现至页面69 if(_page == 1){ 70 document.getElementById("btn1").style.visibility = "hidden";71 document.getElementById(
新闻热点
疑难解答