zoukankan      html  css  js  c++  java
  • 使用nodejs爬取拉勾苏州和上海的.NET职位信息

    最近开始找工作,本人苏州,面了几家都没有结果很是伤心。在拉勾上按照城市苏州关键字.NET来搜索一共才80来个职位,再用薪水一过滤,基本上没几个能投了。再加上最近苏州的房价蹭蹭的长,房贷压力也是非常大,所以有点想往上海去发展。闲来无聊写了个小爬虫,爬了下苏州跟上海的.NET职位的信息,然后简单对比了一下。

    是的小弟擅长.NET,为啥用nodejs?因为前几天有家公司给了个机会可以转nodejs,所以我是用来练手的,不过后来也泡汤了,但是还是花两晚写完了。刚学,代码丑轻喷哈!

    一:如何爬取拉勾的数据

    这个其实非常简单,本来还以为要用正则去分析html,其实拉勾分页提了ajax的接口,可以直接用http去访问。打开神器Chrome的F12一看便知。

    这是用nodejs模拟分页请求的代码:

    var getData = function (kd,city,pn) {
        var mongo = require('./mongo');
        var http = require('http');
        var queryString = require('querystring');
    
        var postData=queryString.stringify({
            'pn':pn,
            'kd':kd,
            'first':false
        });
    
        var options = {
            hostname:'www.lagou.com',
            method:'POST',
            path:'/jobs/positionAjax.json?px=default&city='+city,
            headers: {
            'Content-Type': 'application/x-www-form-urlencoded',
            'Content-Length': postData.length
            }
        };
        
        var postResult = '';
        
        var req = http.request(options,(res)=>{
            console.log(`STATUS:${res.statusCode}`);
            res.setEncoding('utf8');
            res.on('data',(chunk)=>{
                postResult+=chunk;
            }); 
            res.on('end',()=>{
                console.log(`RESULT:${postResult}`);
                var jsonObj =JSON.parse(postResult);
                //insert into db
                jsonObj.content.result.forEach((item)=>{
                    var salary = item.salary;
                    //拆分3k-6k,易于统计
                    var arr = salary.split('-');
                    var min = arr[0].substring(0,arr[0].indexOf('k'));
                    var max = arr.length>1? arr[1].substring(0,arr[1].indexOf('k')):min;
                    item.salaryMin = parseInt(min);
                    item.salaryMax = parseInt(max);
                    
                    mongo.save(city,item);
                });
                if(jsonObj.content.hasNextPage&&jsonObj.content.totalPageCount>pn){
                    getData(kd,city,pn+1);
                }
            });
            req.on('error',(e)=>{
                console.log(`problem with request:${e.message}`);
            }); 
        });
    
        req.write(postData);
        req.end();
        console.log(`start to get data. pn:${pn} city:${city} kd:${kd}`);
    };
    
    exports.run = getData;

    二:数据存储在哪里

    拉勾的分页接口返回的是json对象,那么自然是存mongoDb最简单了。

    下面是mongoDb的封装:

    var save=function (city,jsonObj) {
        var Db = require('mongodb').Db;
        var Server = require('mongodb').Server;
    
        var db = new Db('test',new Server('localhost',27017))
    
        db.open((err,db)=>{
            var coll = db.collection(city);
            coll.save(jsonObj,(err,r)=>{
                if(!err){
                   console.log('save to '+city); 
                }
                
                db.close();
            });
            
        });
    };
    
    var removeAll = function (city,callback) {
        var Db = require('mongodb').Db;
        var Server = require('mongodb').Server;
    
        var db = new Db('test',new Server('localhost',27017))
    
        db.open((err,db)=>{
            var coll = db.collection(city);
            coll.remove((err,numOfRows)=>{
                if(!err){
                    console.log(`${city} collection be removed. ${numOfRows}`);
                }
                db.close();
                callback(err);
            });
          
        });
    };
    
    var readAll=function (city,callback) {
        var Db = require('mongodb').Db;
        var Server = require('mongodb').Server;
    
        var db = new Db('test',new Server('localhost',27017))
    
        db.open((err,db)=>{
            var coll = db.collection(city);
            var cursor = coll.find();
            cursor.toArray((err,results)=>{
                if(!err){
                    callback(results);
                    //db.close();        
                }
                db.close();
            });
        });
    }
    
    exports.save = save;
    exports.removeAll = removeAll;
    exports.readAll = readAll;
     

    三:如何展示数据

    使用nodejs自带的httpServer,接受到请求的时候直接读取一个html文件,然后把对比的信息填入html文本里,用一个h5的chart来展示

    下面是服务器的代码:

    var http = require('http');
    var fs = require('fs');
    var stati = require('./statistics');
    var szStati = {text:'SuZhou'};
    var shStati = {text:'ShangHai'};
    
    var server=new http.Server();  
    server.on('request',function(req,res){  
        res.writeHead(200,{'Content-Type':'text/html'});  
        
        fs.readFile('./index.html','utf8',(err,data)=>{
            if (err) {
                throw err;
            }
            console.log(data);
            // res.write(data);
            // res.end();
            stati.statiSalary('苏州',(results)=>{
                szStati.values = results;
                stati.statiSalary('上海',(results)=>{
                    shStati.values = results;
                    var series =[szStati,shStati];
                    var strSeries = JSON.stringify(series);
                    console.log(strSeries);
                    
                    data = data.replace('@series',strSeries);
                    console.log(data);
                    
                    res.write(data);
                    res.end();
                });
            });
        });
    });  
      
    server.listen(3000);  
    console.log('http server started...port:3000');

    四:统计结果

    统计按照 0-5k,5-10k,10-15k,15-20k,20-25k,>25k这几个区间按照职位的数量进行统计。

    0-5k:上海是苏州的4倍

    5-10k:上海是苏州的4倍

    10-15k:上海是苏州的9倍

    15-20k:上海是苏州的12倍

    20-25k:上海是苏州的17倍

    >25k:上海是苏州的26倍

    可以看到从10-15k开始的职位,上海的数量是苏州的10多倍,越是高薪的职位倍数越高。由此可以看出,苏州跟上海的差距还是非常大的。苏州政府一直沾沾自喜,觉得自己在互联网圈子有多牛逼,搞了一堆孵化器,但其实拿的出手的公司有几家呢,一只手都数过来了,跟北上广深一线还是差的很远呢,还是要努力啊。

    恐怕我也要背井离乡去上海的寻找未来了。

    还没学会用VS Code上传到github上,先直接上传代码吧:lagouSpider.zip

  • 相关阅读:
    Tomcat架构解析(五)-----Tomcat的类加载机制
    session与cookie
    freemarker常用标签解释遍历
    freemarker常用标签解释三
    freemarker常用标签解释二
    freemarker常用标签解释
    禁止浏览器自动填充
    使用cookie实现自动登录
    长连接和短连接
    filter防止xxs攻击
  • 原文地址:https://www.cnblogs.com/kklldog/p/lagouNodeSpider.html
Copyright © 2011-2022 走看看