国产xxxx99真实实拍_久久不雅视频_高清韩国a级特黄毛片_嗯老师别我我受不了了小说

資訊專欄INFORMATION COLUMN

node.js 爬取招聘信息分析各職業錢途(爬蟲+動態IP代理+數據可視化分析)

546669204 / 603人閱讀

摘要:成功爬取了拉鉤網上多個招聘崗位的具體信息后,數據可視化并得出分析結果如下從整體看,北上廣深杭這五個城市前端工程師招聘崗位,北京是遙遙領先,是深圳的兩倍,是廣州的三倍,其次到上海,深圳,杭州,廣州居末。

前前言

本文首發于 github blog

不想看爬蟲過程只想看職位錢途數據分析請看這里:
前端招聘崗位分析
C++招聘崗位分析
JAVA招聘崗位分析
PHP招聘崗位分析
Python招聘崗位分析

想看源碼或想自己爬一個請看這里:本文github源碼

前言

早在一年前大學校招期間,為了充實下簡歷,就寫了個node爬蟲,可惜當時能力有限,工程存在一定的局限性,不好意思拿出來裝逼分享。

一年過去了,現在能力依然有限,但是臉皮卻練厚了,于是就有了這篇文章。

題綱

關于爬蟲,主流技術是用python,然而隨著node的出現,對于對python了解有限的前端同學,用node來實現一個爬蟲也不失為一個不錯的選擇。

當然無論是python爬蟲還是node爬蟲或者其他品種的爬蟲,其實除了語言特性之外,其思路基本大同小異。下面我就為大家詳細介紹下node爬蟲的具體思路與實現,內容大概如下:

爬前準備

選擇目標

分析可收集數據與目標可爬取入口

爬蟲

爬取JSON數據

爬取HTML文檔,提取有用信息

Mongodb 數據存儲

并發控制

動態IP代理(防止IP被禁)

數據可視化展示

爬前準備 選擇目標

既然要寫爬蟲,當然要爬一些利益相關的數據比較好玩啦。爬取招聘網站的招聘信息,來看看互聯網圈子里各個工種的目前薪酬狀況及其發展前景,想來是不錯的選擇。

經我夜觀天下,掐指一算,就選拉勾網吧。

分析可收集數據

一個職位招聘信息,一般來說,我們關注的重點信息會是:

薪酬(毫無疑問,重中之重)

工作城市

學歷要求

工作年限要求

雇主公司

公司領域

公司規模

帶著想要收集的信息,首先,進入拉勾官網,搜索web前端崗位,能看到

很好,我們想要的信息基本都有了。

分析目標可爬取入口 PC端入口

F12 分析請求資源,可得https://www.lagou.com/jobs/positionAjax.json?needAddtionalResult=false&isSchoolJob=0
post 請求體

{
    first:false,
    pn:1,
    kd:`web前端`
}

響應JSON數據

完美!!! 數據格式都已經幫我們整理好了,直接爬就行了。

但,完美的數據總不會這么輕易讓你得到,經我用 nodepython,還有postman 攜帶瀏覽器全部header信息一一測試,均發現:

好吧,此路不通。(此接口反爬蟲機制不明,有研究的大神請留言=_=)

所謂條條大路通羅馬,此路不通,咱繞路走。

移動端入口

經過一番探索,發現 拉勾移動端站點 空門大開!

提示: 一般有點技術含量的網站都可能會存在不同強度的反爬蟲機制,而一般其移動端站點的反爬蟲機制相對于PC站點較弱,是一個不錯的著手點。再不行的話,還可以去其app端抓包分析是否存在想要的請求哦。

GET請求: https://m.lagou.com/search.js...
響應信息:

很好,雖然數據信息有點少,但是總算是一個能爬的接口了。

爬蟲

好了,分析也分析完了,現在正式設計爬蟲程序。

JSON數據爬取

首先,把請求的路徑與參數多帶帶抽離。

let spider = {
    requestUrl : "http://m.lagou.com/search.json",
    query: {
        city: "",
        pageNum: "",
        job: "",
    },
    ...
}

發出請求,此處的服務端構造請求使用 superagent,當然,用 request 等類似的包也可以,并無限定。

let spider = {
    ....
/**
 * 發起單個請求
 * @return {> | >} 請求成功resolve原始數據,否則reject
  **/
    request() {
        return new Promise((resolve,reject)=>{
            superagent
            .get(this.requestUrl)
            .query({
                city: this.query.city,
                pageNo: this.query.pageNum,
                positionName: this.query.job
            }).end((err, res)=>{
                let dataList = [];
                if (err || !res || !res.ok) {
                    console.error(err);
                    reject("request failed!")
                } else  {
                    dataList = res.body.content.data.page.result
                    if (dataList.length === 0) {
                        // 當請求結果數組長度為0,即認為已經到末頁,結束爬蟲
                        reject("finish");                     
                    } else {
                        resolve(dataList)
                    }
                } 
            })
        })
    },
 

處理數據

let spider = {
    ....
/**
 * 處理爬取到的原始數據,提取出所需的數據
 * @param {} - companyList : 原始數據
 * @return {>} resolve處理過的數據
  **/
    handleCallbackData(companyList) {
       
        //處理數據
         let arr = companyList.map((item) => {
            let salary = item.salary.split("-");
            
            //工資兩種情況:”10k以上“ or "10k-15k", 平均工資取中位數
            aveSalary = salary.length == 1 ? parseInt(salary[0])*1000 : (parseInt(salary[0]) + parseInt( salary[1] ) )*500;

            //過濾出所需數據
            return {
                companyFullName: item.companyFullName,
                positionId : item.positionId ,
                salary:aveSalary ,
                city:item.city ,

                field: "",
                companySize:"",
                workYear:"" ,
                qualification: "",
            }
        });

        return Promise.resolve(arr)
    }

保存數據,此處數據庫使用mongodbORM使用 moogoose

save2db(jobList) {
    return new Promise((resolve, reject)=>{
        Job.create(jobList,function (err,product) {
            if (err) {
                console.error(err.errmsg)
                err.code == 11000 && resolve("丟棄重復數據")
                reject(err);
            } else {
                resolve("save data to database successfully")
            }
        })    
    })
},

HTML 數據解析爬取

從上述的json數據其實我們可以看到,JSON返回的信息十分有限,那么我們需要爬取更多的信息,就需要在招聘詳情頁解析 html 后提取出所需的信息
隨便打開一個移動端的招聘詳情頁https://m.lagou.com/jobs/3638173.html,目測出url結構很簡單,就是jobs/{{positionId}}.html

從詳情頁中可以找出 JSON 數據中缺少的數據項:工作年限要求,學歷要求,雇主公司領域,雇主公司融資情況,雇主公司規模大小。

爬取方法和上述爬取 JSON 數據相差無幾,主要差別就是數據解析部分,這里需要用到cherrio來解析 爬取到的HTML,從而更簡單地提取必要信息。

    handleCallbackData({res, jobId}) {
        var $ = cheerio.load(res.text);

        let workYear = $("#content > div.detail > div.items > span.item.workyear > span").text(),
            qualification = $("#content > div.detail > div.items > span.item.education").text().trim(),
            field = $("#content > div.company.activeable > div > div > p").text().trim().split(/s*/s*/)[0]
            companySize = $("#content > div.company.activeable > div > div > p").text().trim().split(/s*/s*/)[2];

        /* 如果這四項數據都沒有提取到,很有可能是被拉勾的反爬蟲機制攔截了 */
        if ( !(workYear || qualification || field || companySize) ) {
            console.log(res.text)
            return Promise.reject({code:-1, msg:"wrong response!", jobId});
        }

        return {
            id: jobId,
            jobInfo: {
                workYear,
                qualification,
                field,
                // financeStage,
                companySize,
            }
        }
    },
并發控制

做過爬蟲的都知道,爬蟲的請求并發量是必須要做的,為什么要控制并發?

控制其爬取頻率,以免沒爬幾個就網站被封IP了。

控制爬蟲應用運行內存,不控制并發的話一下子處理N個請求,內存分分鐘爆炸。

實現并發控制可以使用npm包 async.mapLimit,這里為了自由度更大我使用了自己實現的 15 行代碼實現并發控制。

具體代碼如下:

let ids = [2213545,5332233, ...], // 招聘崗位詳情id列表
    limit = 10, // 并發數
    runningRequestNum = 0 , // 當前并發數
    count = 0; // 累計爬取數據項計數
    
mapLimit(ids, limit, async (jobId)=>{
    let requestUrl = `http://m.lagou.com/jobs/${jobId}.html?source=home_hot&i=home_hot-6` ;
    let delay = parseInt(Math.random() * 2000);

    let currentIndex = count++;
    runningRequestNum++

    await sleep( delay );  // 避免爬太快被封ip,休眠一兩秒
    
    let result = await spiderHTML.run({
                    requestUrl,
                    jobId,
                    proxyIp
                })
    console.log(`當前并發數`, runningRequestNum)
    runningRequestNum--
    
    return result;
}).then(mapResult => {
    // 并發控制下將 ids 全部迭代完畢
    // do something 
})



然而,即便嚴格控制了請求頻率,我們還是不可避免地中招了。

對于反爬蟲措施比較暴躁的網站來說,一個IP爬取太過頻繁,被識別成機器爬蟲幾乎是不可避免的。

一般來講,我們最簡單直接的方法就是:換IP。這個IP訪問頻率太高了被反爬攔截到,換個IP就行了嘛。

動態IP代理

單個IP爬蟲對于反爬較為嚴厲的網站是走不通的。那么我們需要用到動態IP池,每次爬取時從IP池中拉取一個IP出來爬數據。

道理很簡單,
1秒內1個IP訪問了100個頁面,即便是單身20多年的手速也無法企及。只能是機器爬蟲無疑。
但1秒內100個IP訪問100個頁面,平均每個IP一秒內訪問了1個頁面,那基本不會被反爬干掉

怎么搭建動態IP池?

首先我們得有一個IP源,動態IP池的補充都從這里拉取,這個網上搜一下"免費代理IP"就有很多出來,選其中一個,收費的IP源比較穩定可靠,免費的就一分錢一分貨了。

其次,每次從IP源中拉取的IP都是無法確認其是否可用的,我們必須篩選一遍,提取出可用的IP。(PS: 此處和步驟4目的一直,如果IP源較為可靠,可以省略)

設計從IP池中拉取單個IP的策略,使得每個IP使用頻率均勻,盡量避免單個IP使用頻率過高而失效。

移除失效IP。盡管設計了拉取策略,但依舊不可避免某些IP失效,此時需要將其移出IP池廢棄。

動態IP池工作流程:

st=>start: 提取一個可用IP
e=>end: 根據策略返回一個可用IP
isEnought=>condition: 池中IP數量是否足夠
fetch=>operation: 從IP源拉取IP
valid=>operation: 篩選出有效IP并存入IP池
st->isEnought(yes)->e
isEnought(no,right)->fetch(right)->valid(right)->isEnought

具體實現代碼其實和上面的爬蟲差不多,無非就是爬崗位變成了爬IP而已,具體實現源碼在這,就不在這寫了。

數據可視化分析

我們最終折騰爬蟲,無非就是想要看爬到的數據到底說明了什么。
成功爬取了拉鉤網上多個招聘崗位的具體信息后,數據可視化并得出分析結果如下:


從整體看,北上廣深杭這五個城市前端工程師招聘崗位,北京是遙遙領先,是深圳的兩倍,是廣州的三倍,其次到上海,深圳,杭州,廣州居末。

從需求量大概可以看出,整體互聯網產業發達程度是 北 > 上 > 深 > 杭 > 廣


由平均工資曲線圖可以看到,每隔2K算一檔的話,北京一檔,上海一檔,杭州深圳一檔,空一檔,廣州吊車尾,杭州竟然比深圳高了300,這就代表著深圳雖然招聘需求比杭州大,但兩者薪酬待遇其實差不多。

從不同薪酬的招聘數量也能看出一些很大的區別,招聘提供薪資水平中,普遍數量最多的是10k-20k這個水平,但,北京牛逼,招聘崗位60%以上都是20K以上的。我們具體來看看,各個城市對高端人才(提供薪酬20k以上)的招聘比例,那就可以看出明顯區別了:

北京:招聘的薪資水平是"20k以上",大概是招聘總數的59.7%

上海:招聘的薪資水平是"20k以上",大概是招聘總數的41.3%

深圳:招聘的薪資水平是"20k以上",大概是招聘總數的29.2%

杭州:招聘的薪資水平是"20k以上",大概是招聘總數的30.4%,和深圳相差不大

廣州:招聘的薪資水平是"20k以上",大概是招聘總數的……10.4%。


基本可以看到一個明顯的趨勢,公司規模越大,能提供的薪酬越高,不差錢。
另外,從不同規模的公司的前端招聘數量來看,北京又一枝獨秀,大公司招聘需求很高。

但從全國來看,不同規模的公司(除了15人以下的)招聘數量基本在同一水平,基本說明:大公司少,但是每個公司招聘的人多;小公司多,但是每個公司招聘的人少。好像這是句廢話。


從圖上看,工作經歷在1-5年的現在需求最旺盛,并且理所當然地,工作資歷越高,薪資越高。
其中3-5年的最吃香,廣州有點奇怪,1-3年的最吃香?綜合上面的多項數據,感覺像是1-3年工資比3-5年低所以廣州互聯網公司多招1-3年

當然,這里存在這一個幸存者偏差,拉勾上大部分的都是社招性質的招聘,而應屆生和1年經驗的大部分都跑校招去了吧,所以數量低也不出奇。


移動互聯網占據了大半壁江山,剩下之中,金融,電子商務,企業服務,數據服務在同一層次。另外,物聯網,智能硬件各有一招聘崗位,薪酬都是5K...嗯雖說node現在也可以做物聯網了(還別說,我還真的用node搞過硬件串口通信Orz),但是終究不是主流技術,數據展示表明,前端基本與硬件絕緣。

薪酬待遇倒是都在同一水平上,“大數據”工資倒是一枝獨秀,但是數據量太少,參考價值不大。

總結:北京錢多機會多當之無愧第一檔;上海稍遜一籌;杭州深圳又低一籌;廣州真的是差了兩個身位。 而對于前端來說,北京 移動互聯網 大公司,錢多!坑多!速來!

文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。

轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/93896.html

相關文章

  • 前程無憂崗位數據爬取+Tableau視化分析

    摘要:實際上,前程無憂招聘網站上與數據有關的只有幾百頁,而我們爬取了頁的所有數據,因此在后面進行數據處理時需要把無關的數據剔除掉。 目錄 一、項目背景 二、數據爬取 1、相關庫的導入與說明 2、獲取二級頁面鏈接 1)分析一級頁面url特征 2)構建一級url庫 3)爬取所有二級url鏈接 3、獲取...

    233jl 評論0 收藏0
  • ?Echarts統計拉勾網招聘信息(scrapy 爬取

    摘要:因為本人在成都從事前端,所以這次爬取的關鍵詞既是成都,前端。僅僅有這個是不夠的,因為貌似拉勾網有反爬蟲,沒有好像得不到數據這個還待論證,至少我這邊是。 前言 showImg(https://segmentfault.com/img/bV1g4S?w=700&h=490); 今天是2018的第一天,首先祝各位小伙伴元旦快樂!又到了新的一年,雖然離春節還有一段時間,但是程序狗打工不易啊,不...

    genefy 評論0 收藏0
  • ?Echarts統計拉勾網招聘信息(scrapy 爬取

    摘要:因為本人在成都從事前端,所以這次爬取的關鍵詞既是成都,前端。僅僅有這個是不夠的,因為貌似拉勾網有反爬蟲,沒有好像得不到數據這個還待論證,至少我這邊是。 前言 showImg(https://segmentfault.com/img/bV1g4S?w=700&h=490); 今天是2018的第一天,首先祝各位小伙伴元旦快樂!又到了新的一年,雖然離春節還有一段時間,但是程序狗打工不易啊,不...

    Jingbin_ 評論0 收藏0
  • 區塊鏈招聘信息爬取分析

    摘要:最近在研究區塊鏈,閑來無事抓取了拉勾網上條區塊鏈相關的招聘信息。拉勾網的反爬蟲做的還是比較好的,畢竟自己也知道這種做招聘信息聚合的網站很容易被爬,而且比起妹子圖這種網站,開發的技術水平應該高不少。 最近在研究區塊鏈,閑來無事抓取了拉勾網上450條區塊鏈相關的招聘信息。過程及結果如下。 拉勾網爬取 首先是從拉勾網爬取數據,用的requests庫。拉勾網的反爬蟲做的還是比較好的,畢竟自己也...

    kelvinlee 評論0 收藏0
  • node.js 89行爬蟲爬取智聯招聘信息

    摘要:智聯其實一共寫了兩次,有興趣的可以在源碼看看,第一版的是回調版,只能一次一頁的爬取。 寫在前面的話,    .......還是不寫了,直接上效果圖。附上源碼地址 github.lonhon showImg(https://segmentfault.com/img/bVUM3F?w=714&h=543);showImg(https://segmentfault.com/img/bVUM...

    _ivan 評論0 收藏0

發表評論

0條評論

最新活動
閱讀需要支付1元查看
<