最近準備換工作,需要更新一下技能樹。為做到有的放矢,想對招聘方的要求做個統計。正好之前瞭解過nodejs,所以做了個爬蟲搜索數據。 具體步驟: 1. 先用fiddler分析請求需要的header和body。 2. 再用superagent構建上述數據發送客戶端請求。 3. 最後對返回的數據使用che ...
最近準備換工作,需要更新一下技能樹。為做到有的放矢,想對招聘方的要求做個統計。正好之前瞭解過nodejs,所以做了個爬蟲搜索數據。
具體步驟:
1. 先用fiddler分析請求需要的header和body。
2. 再用superagent構建上述數據發送客戶端請求。
3. 最後對返回的數據使用cheerio整理。
折騰了幾個晚上,只搞出了個架子,剩餘工作等有時間再繼續開發。
/*使用fiddler抓包,需要配置lan代理,且設置如下參數*/ process.env.https_proxy = "http://127.0.0.1:8888"; process.env.http_proxy = "http://127.0.0.1:8888"; process.env.NODE_TLS_REJECT_UNAUTHORIZED = "0"; /*使用到的模塊*/ var request = require('superagent'); //發送客戶端請求 require('superagent-proxy')(request); //使用代理髮送請求 var cheerio = require('cheerio'); //以jq類似的方法操作返回的字元,不需要用正則 require('superagent-charset')(request);//node不支持gbk,gb2312,this will add request.Request.prototype.charset. var async = require('async'); //非同步流控制模塊 var fs = require('fs'); /*相關參數,通過fiddler抓包後複製過來*/ var ws = fs.createWriteStream('res.html',{flags:'w+'}); //a+追加的讀寫模式,w+覆蓋 var loginUrl = "https://login.51job.com/login.php"; var searchUrl = "http://search.51job.com/jobsearch/search_result.php"; var queryStrings = "fromJs=1&jobarea=020000&keyword=%E5%89%8D%E7%AB%AF%E5%BC%80%E5%8F%91&keywordtype=2&lang=c&stype=2&postchannel=0000&fromType=1&confirmdate=9"; var loginForms = { lang: 'c', action: 'save', from_domain: 'i', loginname: '***', //自己的用戶名和密碼 password: '***', verifycode: '', isread: 'on' }; var searchForms = { lang: 'c', stype: '2', postchannel: '0000', fromType: '1', line: '', confirmdate: '9', from: '', keywordtype: '2', keyword: '%E5%89%8D%E7%AB%AF%E5%BC%80%E5%8F%91', jobarea: '020000', industrytype: '', funtype: '' }; var searchFormsString='lang=c&stype=2&postchannel=0000&fromType=1&line=&confirmdate=9&from=&keywordtype=2&keyword=%C7%B0%B6%CB%BF%AA%B7%A2&jobarea=020000&industrytype=&funtype='; var proxy0 = process.env.https_proxy; var proxy = process.env.http_proxy; const agent = request.agent(); //agent()方法產生的實例會保存cookie供後續使用 request.post(loginUrl).proxy(proxy0).send(loginForms).end(function (err,res0) { agent.post(searchUrl) .proxy(proxy) //proxy()方法需緊跟在method方法之後調用,否則fiddler抓不到數據包 .type('application/x-www-form-urlencoded') .query(queryStrings) //使用字元串格式 .send(searchFormsString) .charset('gbk') //通過charset可知編碼字元格式,不設置會有亂碼 .end(function (err, res) { /* 以下是處理返回數據的邏輯代碼*/ var $ = cheerio.load(res.text); //res.text是返回的報文主體 async.each($('.el.title').nextAll('.el'), function(v, callback) { //將多餘的內容刪除,保留崗位、公司鏈接 $(v).prepend($(v).find('.t1 a')); $(v).find('.t1').remove(); ws.write($.html(v), 'utf8'); }, function(err) { console.log(err); }); console.log('successful'); }) }); //jquery內置document元素為root,cheerio需要通過load方法傳入,然後用選擇器查找指定元素,再執行相應操作。 // $.html(el);靜態方法,返回el元素的outerHtml //TODO // 1.當前只請求到一頁數據,還需構建所有頁數的請求列表 // 2.向每條數據的崗位鏈接發送請求,獲取技能關鍵字,存入文件中 // 3.node中io操作是非同步的,且沒有鎖的概念,如何併發地向同一個文件正確地寫入數據
結果顯示如下: