前天剛考完編譯,今天考完網絡,就開始搗鼓代碼了,花了一天時間摸索了一下
nodejs
的爬蟲,也就是tcp
,http
鏈接。javascript
也是就作了一個爬取煎蛋網妹子圖的爬蟲,並保持至本地。php
經過http請求報文
模擬一次訪問煎蛋網的操做html
獲取到了網頁的HTML代碼後,進行正則表達式匹配,獲得圖片地址java
經過圖片地址,再次發送http請求報文
,將圖片數據保存至本地node
思路簡單瞭解後,便開始工做了。git
HTML
?參考資料http://chenxi.name/60.html,利用request
包進行傻瓜式調用,然而並不能生效,將會跳轉至一個屏蔽提示網頁github
煎蛋網爲了防止惡意爬取數據,進行了必定程度的防爬措施。但這可難不倒我,爲何在瀏覽器上就能正常瀏覽圖片頁面呢?web
因而我打開瀏覽器控制檯,複製頁面請求報文的cmd格式,粘貼至命令行中運行,可以正確獲得HTML
。正則表達式
因此,我以爲問題就是出如今請求報文頭部數據,因而複製下瀏覽器中報頭,利用nodejs
的http
包,創建http鏈接。api
require('http').get({ hostname:'jandan.net', path:'/', header:{ ... } },function(res){ })
可是奇怪的是!仍是響應302,跳轉至屏蔽提示頁面。
最後沒辦法的我只好利用底層一點的api——net
包,創建tcp鏈接,發送符合http請求報文
格式的數據。
var net = require('net'); var header = require('fs').readFileSync('./header.txt').toString(); module.exports = function (path,callback) { const socket = net.createConnection(80,'jandan.net'); socket.write( 'GET '+path+' HTTP/1.1\r\n'+ header ); socket.setEncoding('utf-8'); socket.setTimeout(4000,function () { callback(html); console.error(new Error('Time OUT')); socket.end(); }); var html = ''; socket.on('data',function (chunk) { html+=chunk; }); socket.on('end',function () { console.log('disconnected from server'); }); }
header.txt
Host: jandan.net Connection: keep-alive Cache-Control: max-age=0 Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8 Upgrade-Insecure-Requests: 1 User-Agent: Mozilla/5.0 (Windows NT 6.2; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/45.0.2454.101 Safari/537.36 Referer: http://jandan.net/v Accept-Language: zh-CN,zh;q=0.8 Cookie: gif-click-load=on; bad-click-load=on; PHPSESSID=u1gnmqnpb75injakbgvkb6r413; 4036050675=c119Yp%2BLrMWuv%2BWMyYtq3x6vTdbFzaTbUyoiLt%2Fv; jdna=596e6fb28c1bb47f949e65e1ae03f7f5#1467288596467; Hm_lvt_fd93b7fb546adcfbcf80c4fc2b54da2c=1467287791; Hm_lpvt_fd93b7fb546adcfbcf80c4fc2b54da2c=1467288598; _ga=GA1.2.330681373.1467287790
注意,header.txt最後須要兩個\r\n
表示請求報頭結束。最後果真是成功了,但具體兩種方法的不一樣我也說不上來,但願有熱心讀者能告訴我。
利用下面的遞歸方法加上Promise.all
同步方法,防止過分的tcp鏈接(改用下面方法後,tcp讀寫錯誤明顯減小,但仍是會出現,不知道有沒有大神幫我解決該問題呢?)
function run(i,low) { if(i<low) return; spider('/ooxx/page-'+i,function (html) { var images = []; html.replace(/<img.+?src="(http.+?sina.+?)"/g,function (m,c) { images.unshift(c); }); var page = i; var proms = images.map((x,i,a)=>{ return new Promise((resolve,reject)=>{ var req = http.get(x,function (res) { res.on('error',function (err) { console.error(err); resolve('fail'); }); var filename = x.substr(x.lastIndexOf('/')+1); download(dir+'/'+filename,res); console.log('PAGE:'+page+'...'+filename+'...'+(i+1)+'/'+a.length); resolve('done'); }).end(); }); }); Promise.all(proms) .then((values)=>{ //上一頁的圖片加入下載隊列後,再開始遞歸下一頁。 run(i-1,low); }); }); }
最後文件夾就像下面同樣!
關注個人博客moyuyc.github.io ,有技術的老司機帶你飆車!