根據需求所得五個模塊javascript
// 請求模塊(1.訪問網站) const request = require('request'); // 能夠看作成node版的jQuery(2.獲取頁面指定數據源) const cheerio = require("cheerio"); // node異步流程控制 異步循環(3.根據頁面數據源再訪問詳情數據) const async = require("async"); // Excel表格導出+node自帶文件系統(4.以Excel形式導出) const excelPort = require('excel-export'); const fs = require("fs");
安裝模塊:php
npm install request cheerio async excel-export --save-dev
一開始我直接用request請求網站,但直接返回了404,但我在瀏覽器上看又是沒毛病的。而後我就改了下請求的header。嘻嘻html
request({ url: 'http://www.foo.cn?page=1', method: 'get', headers: { 'User-Agent': 'Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.169 Safari/537.36', 'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3', // 這裏巨坑!這裏開啓了gzip的話http返回來的是Buffer。 // 'Accept-Encoding': 'gzip, deflate', 'Accept-Language': 'zh-CN,zh;q=0.9', 'Cache-Control': 'no-cache', }, // 想請求回來的html不是亂碼的話必須開啓encoding爲null encoding: null }, (err, res, body) => { // 這樣就能夠直接獲取請求回來html了 console.log('打印HTML', body.toString()); // <html>xxxx</html> } );
request({ url: 'http://www.foo.cn?page=1', method: 'get', headers: { 'User-Agent': 'Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.169 Safari/537.36', 'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3', // 'Accept-Encoding': 'gzip, deflate', 'Accept-Language': 'zh-CN,zh;q=0.9', 'Cache-Control': 'no-cache', }, encoding: null }, (err, res, body) => { console.log('打印HTML', body.toString()); // <html>xxxx</html> const list = []; const $ = cheerio.load(body.toString()); // 獲取指定元素 let item = $('.className tbody tr'); // 循環獲得元素的跳轉地址和名稱 item.map((i, index) => { let obj = {}; obj.link = $(index).children('a').attr('href'); obj.name = $(index).children('a').text(); list.push(obj); }); console.log('list', list); // [{ link: 'http://xxxx.com', name: 'abc' }] } );
先將request封裝多一層,傳入page值和async.series的callbackjava
async function requestPage(page = 1, callback) { request({ url: 'http://www.masuma.cn/product.php?lm=21&page=' + page, method: 'get', headers: { 'User-Agent': 'Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.169 Safari/537.36', 'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3', // 'Accept-Encoding': 'gzip, deflate', 'Accept-Language': 'zh-CN,zh;q=0.9', 'Cache-Control': 'no-cache', }, encoding: null }, async (err, res, body) => { console.log('打印HTML', body.toString()); // <html>xxxx</html> const list = []; const $ = cheerio.load(body.toString()); // 獲取指定元素 let item = $('.className tbody tr'); // 循環獲得元素的跳轉地址和名稱 item.map((i, index) => { let obj = {}; obj.link = $(index).children('a').attr('href'); obj.name = $(index).children('a').text(); list.push(obj); }); console.log('list', list); // [{ link: 'http://xxxx.com', name: 'abc' }] callback(null, list); } ); }
async function main() { const requestList = []; // 在這裏爲何要用到async.series? // 是由於這個爬蟲須要具備順序性,必須得異步請求完一個地址並獲取數據而後再存到一個變量裏才能執行下一個 // 在此期間我想過其餘方法。例如: // for循環 + await 直接否認了 // Promise.all這個並不能保證數據具備順序 // 最終敲定用async.series 用完以後!真香啊! // 很好奇async.series找個時間也作個源碼解析 for (let i = 1; i < 36; i++) { requestList.push(callback => { requestPage(i, callback); }); } console.log('requestList', requestList); // [Function, Function] 全是function的數組 async.series(requestList, (err, result) => { // 由於async.series返回來的結果是[[], [], []]這種二維數組形式,每一個function返回來的值都放在一個數組裏,咱們須要將它弄成一維數組好作導出列表 const arry = [].concat.apply([], result); console.log('最終結果!!!!', arry); // [{ link: 'http://xxxx.com', name: 'abc' }, ...] writeExcel(arry); }); } const writeExcel = (datas) => { // 定義一個對象,存放內容 let conf = {}; // 定義表頭 conf.cols = [ {caption:'瑪速瑪編碼', type:'string', width:40}, {caption:'原廠編碼', type:'string', width:60}, ]; // 建立一個數組用來屢次遍歷行數據 let array = []; // 循環導入從傳參中獲取的表內容 for (let i=0;i<datas.length;i++){ //依次寫入 array[i] = [ datas[i].name, datas[i].code, ]; } // 寫入道conf對象中 conf.rows = array; // 生成表格 const result = excelPort.execute(conf); // 定義表格存放路徑 fs.writeFile('./表格.xlsx', result, 'binary',function(err){ if(err){ console.log(err); } }); } main();
其實爬蟲就是:node
其實這個爬蟲最終是web
但我在這裏就寫了獲取各頁表格裏的連接地址,由於在這裏我只想作一個簡單的分享。數據庫
這些分享應該都足以舉一反三了。npm