http模塊內(nèi)部封裝了http服務(wù)器和客戶端,因此Node.js不需要借助Apache、IIS、Nginx、Tomcat等傳統(tǒng)HTTP服務(wù)器,就可以構(gòu)建http服務(wù)器,亦可以用來做一些爬蟲。下面簡單介紹該模塊的使用,其具體API,大家可以自行去nodejs官方文檔查看。
1、http.Server服務(wù)器
使用http.createServer([requestListener])
方法創(chuàng)建一個http服務(wù)器,該方法返回一個新的http.Server實例,如果指定了requestListener,則會自動添加request
事件。http.Server繼承于net.Server,故默認(rèn)擁有很多的屬性、方法和事件,如下圖所示(只給出部分):
使用如下所示:
const http = require('http');const server = http.createServer();server.on('request', (req, res) => { res.writeHead(200, { 'content-type': 'text/plain' }); res.end('hello world');});server.on('listening', () => { console.log(`Server is lintening on ${server.address().address}:${server.address().port}`);});server.listen(3000);
代碼中的request
事件監(jiān)聽的參數(shù)req,res分別是http.IncomingMessage
,http.ServerResponse
的實例,IncomingMessage對象是由 http.Server 或 http.ClientRequest 創(chuàng)建,并且被自動添加到'request' and 'response' 事件監(jiān)聽函數(shù)的第一個參數(shù),是一個可讀流,主要包括一些狀態(tài)信息,請求信息,屬性如下所示:
ServerResponse對象是HTTP server內(nèi)部創(chuàng)建,并作為request
事件監(jiān)聽函數(shù)的第二個參數(shù),實現(xiàn)了可寫流,決定返回給客戶端的內(nèi)容,屬性如下所示:
創(chuàng)建一個http服務(wù)器,并監(jiān)聽3000端口,用瀏覽器打開http://127.0.0.1:3000瀏覽,即可看到hello world
。
我們還可以創(chuàng)建一個簡易的路由,對用戶的請求進(jìn)行處理,如下所示:
//router.jsmodule.exports = router;function router(req,res,pathname,handle){ if(typeof handle[pathname] === 'function'){ return handle[pathname](req,res); }else{ res.writeHead(200,{'Content-Type':'text/html'}); res.end('The request is not found!'); }}//handle.jsconst dns = require('dns');const fs = require('fs');const qs = require('querystring');function showIndex(req,res){ ...}function lookup(req,res){ ...}exports['/'] = showIndex;exports['/dnslookup'] = lookup;
2、http.ClientRequest客戶端
該對象通過http.request()
或http.get()
方法創(chuàng)建,可以作為一個向服務(wù)器發(fā)起請求的客戶端,該對象的屬性(只列出部分)如下:
http.request(options[, callback])方法使用
參數(shù)options
可以是一個對象或字符串,如果是字符串則會自動調(diào)用url.parse()
進(jìn)行解析,包涵以下屬性(部分):
protocol,協(xié)議,默認(rèn)為http:
host,主機地址
hostname,主機名
family,IP版本
port,端口
method,請求方法
path ,路徑
headers ,請求頭
timeout ,超時時間
callback會自動添加給reponse
事件監(jiān)聽,返回值為http.ClientRequest,下面利用該知識寫一個利用支付寶接口查詢銀行卡號所屬銀行,不過http換成了https,接口一致,代碼如下:
const https = require('https');const banknames = require('./bankname.js');const btypes = { DC: '借記卡', CC: '信用卡'};var baseUrl = 'https://ccdcapi.alipay.com/validateAndCacheCardInfo.json?_input_charset=utf-8&cardBinCheck=true&cardNo=';var cardNo = process.argv.slice(2)[0];if (!/^\d{16,}$/.test(cardNo)) { console.log(`參數(shù)錯誤,請輸入16位以上銀行卡號。例如:node http-get.js 6228430120000000000`); process.exit(0);}baseUrl = baseUrl + cardNo;const client = https.get(baseUrl, (res) => { const status = res.statusCode; const type = res.headers['content-type']; let msg = ''; let data = ''; if (status !== 200) { msg = '發(fā)送請求失敗 code:' + statusCode; } else if (!/^application\/json/.test(type)) { msg = '返回的數(shù)據(jù)格式不正確,應(yīng)返回JSON'; } if (msg != '') { console.log(msg); process.exit(0); } res.setEncoding('utf8'); res.on('data', (chunk) => { data += chunk; }); res.on('end', () => { try { let bankObj = JSON.parse(data); dealBankObj(bankObj); } catch (e) { console.log(e.message); } });});client.on('error', (err) => { console.log(err.message);});function dealBankObj(obj) { const bname = banknames[obj['bank']]; const btype = obj['cardType']; const cardId = obj['key']; console.log(`卡號:${cardNo}\r\n銀行:${bname}\r\n類型:${btypes[btype]}`);}
bankname.js
const banknames = { "SRCB": "深圳農(nóng)村商業(yè)銀行", "BGB": "廣西北部灣銀行", "SHRCB": "上海農(nóng)村商業(yè)銀行", "BJBANK": "北京銀行", "WHCCB": "威海市商業(yè)銀行", "BOZK": "周口銀行", "KORLABANK": "庫爾勒市商業(yè)銀行", "SPABANK": "平安銀行", "SDEB": "順德農(nóng)商銀行", "HURCB": "湖北省農(nóng)村信用社", "WRCB": "無錫農(nóng)村商業(yè)銀行", "BOCY": "朝陽銀行", "CZBANK": "浙商銀行", "HDBANK": "邯鄲銀行", "BOC": "中國銀行", "BOD": "東莞銀行", "CCB": "中國建設(shè)銀行", "ZYCBANK": "遵義市商業(yè)銀行", "SXCB": "紹興銀行", "GZRCU": "貴州省農(nóng)村信用社", "ZJKCCB": "張家口市商業(yè)銀行", "BOJZ": "錦州銀行", "BOP": "平頂山銀行", "HKB": "漢口銀行", "SPDB": "上海浦東發(fā)展銀行", "NXRCU": "寧夏黃河農(nóng)村商業(yè)銀行", "NYNB": "廣東南粵銀行", "GRCB": "廣州農(nóng)商銀行", "BOSZ": "蘇州銀行", "HZCB": "杭州銀行", "HSBK": "衡水銀行", "HBC": "湖北銀行", "JXBANK": "嘉興銀行", "HRXJB": "華融湘江銀行", "BODD": "丹東銀行", "AYCB": "安陽銀行", "EGBANK": "恒豐銀行", "CDB": "國家開發(fā)銀行", "TCRCB": "江蘇太倉農(nóng)村商業(yè)銀行", "NJCB": "南京銀行", "ZZBANK": "鄭州銀行", "DYCB": "德陽商業(yè)銀行", "YBCCB": "宜賓市商業(yè)銀行", "SCRCU": "四川省農(nóng)村信用", "KLB": "昆侖銀行", "LSBANK": "萊商銀行", "YDRCB": "堯都農(nóng)商行", "CCQTGB": "重慶三峽銀行", "FDB": "富滇銀行", "JSRCU": "江蘇省農(nóng)村信用聯(lián)合社", "JNBANK": "濟(jì)寧銀行", "CMB": "招商銀行", "JINCHB": "晉城銀行JCBANK", "FXCB": "阜新銀行", "WHRCB": "武漢農(nóng)村商業(yè)銀行", "HBYCBANK": "湖北銀行宜昌分行", "TZCB": "臺州銀行", "TACCB": "泰安市商業(yè)銀行", "XCYH": "許昌銀行", "CEB": "中國光大銀行", "NXBANK": "寧夏銀行", "HSBANK": "徽商銀行", "JJBANK": "九江銀行", "NHQS": "農(nóng)信銀清算中心", "MTBANK": "浙江民泰商業(yè)銀行", "LANGFB": "廊坊銀行", "ASCB": "鞍山銀行", "KSRB": "昆山農(nóng)村商業(yè)銀行", "YXCCB": "玉溪市商業(yè)銀行", "DLB": "大連銀行", "DRCBCL": "東莞農(nóng)村商業(yè)銀行", "GCB": "廣州銀行", "NBBANK": "寧波銀行", "BOYK": "營口銀行", "SXRCCU": "陜西信合", "GLBANK": "桂林銀行", "BOQH": "青海銀行", "CDRCB": "成都農(nóng)商銀行", "QDCCB": "青島銀行", "HKBEA": "東亞銀行", "HBHSBANK": "湖北銀行黃石分行", "WZCB": "溫州銀行", "TRCB": "天津農(nóng)商銀行", "QLBANK": "齊魯銀行", "GDRCC": "廣東省農(nóng)村信用社聯(lián)合社", "ZJTLCB": "浙江泰隆商業(yè)銀行", "GZB": "贛州銀行", "GYCB": "貴陽市商業(yè)銀行", "CQBANK": "重慶銀行", "DAQINGB": "龍江銀行", "CGNB": "南充市商業(yè)銀行", "SCCB": "三門峽銀行", "CSRCB": "常熟農(nóng)村商業(yè)銀行", "SHBANK": "上海銀行", "JLBANK": "吉林銀行", "CZRCB": "常州農(nóng)村信用聯(lián)社", "BANKWF": "濰坊銀行", "ZRCBANK": "張家港農(nóng)村商業(yè)銀行", "FJHXBC": "福建海峽銀行", "ZJNX": "浙江省農(nóng)村信用社聯(lián)合社", "LZYH": "蘭州銀行", "JSB": "晉商銀行", "BOHAIB": "渤海銀行", "CZCB": "浙江稠州商業(yè)銀行", "YQCCB": "陽泉銀行", "SJBANK": "盛京銀行", "XABANK": "西安銀行", "BSB": "包商銀行", "JSBANK": "江蘇銀行", "FSCB": "撫順銀行", "HNRCU": "河南省農(nóng)村信用", "COMM": "交通銀行", "XTB": "邢臺銀行", "CITIC": "中信銀行", "HXBANK": "華夏銀行", "HNRCC": "湖南省農(nóng)村信用社", "DYCCB": "東營市商業(yè)銀行", "ORBANK": "鄂爾多斯銀行", "BJRCB": "北京農(nóng)村商業(yè)銀行", "XYBANK": "信陽銀行", "ZGCCB": "自貢市商業(yè)銀行", "CDCB": "成都銀行", "HANABANK": "韓亞銀行", "CMBC": "中國民生銀行", "LYBANK": "洛陽銀行", "GDB": "廣東發(fā)展銀行", "ZBCB": "齊商銀行", "CBKF": "開封市商業(yè)銀行", "H3CB": "內(nèi)蒙古銀行", "CIB": "興業(yè)銀行", "CRCBANK": "重慶農(nóng)村商業(yè)銀行", "SZSBK": "石嘴山銀行", "DZBANK": "德州銀行", "SRBANK": "上饒銀行", "LSCCB": "樂山市商業(yè)銀行", "JXRCU": "江西省農(nóng)村信用", "ICBC": "中國工商銀行", "JZBANK": "晉中市商業(yè)銀行", "HZCCB": "湖州市商業(yè)銀行", "NHB": "南海農(nóng)村信用聯(lián)社", "XXBANK": "新鄉(xiāng)銀行", "JRCB": "江蘇江陰農(nóng)村商業(yè)銀行", "YNRCC": "云南省農(nóng)村信用社", "ABC": "中國農(nóng)業(yè)銀行", "GXRCU": "廣西省農(nóng)村信用", "PSBC": "中國郵政儲蓄銀行", "BZMD": "駐馬店銀行", "ARCU": "安徽省農(nóng)村信用社", "GSRCU": "甘肅省農(nóng)村信用", "LYCB": "遼陽市商業(yè)銀行", "JLRCU": "吉林農(nóng)信", "URMQCCB": "烏魯木齊市商業(yè)銀行", "XLBANK": "中山小欖村鎮(zhèn)銀行", "CSCB": "長沙銀行", "JHBANK": "金華銀行", "BHB": "河北銀行", "NBYZ": "鄞州銀行", "LSBC": "臨商銀行", "BOCD": "承德銀行", "SDRCU": "山東農(nóng)信", "NCB": "南昌銀行", "TCCB": "天津銀行", "WJRCB": "吳江農(nóng)商銀行", "CBBQS": "城市商業(yè)銀行資金清算中心", "HBRCU": "河北省農(nóng)村信用社"};module.exports = banknames;
執(zhí)行結(jié)果如下所示:
E:\developmentdocument\nodejsdemo>node http-get.js 6228430120000000000
卡號:6228430120000000000
銀行:中國農(nóng)業(yè)銀行
類型:借記卡
下面再舉一個爬蟲例子,利用百度和360搜索的數(shù)據(jù),驗證電話號碼是否騷擾電話,需要cheerio庫,該庫類似jquery,語法大部分一致,使用npm安裝:
npm install cheerio
我們對兩個搜索引擎搜索指定電話號碼的結(jié)果進(jìn)行分析,如果是騷擾號碼則打印出被標(biāo)記多少次,否則打印其歸屬地,實現(xiàn)如下所示:
const https = require('https');const http = require('http');const url = require('url');const cheerio = require('cheerio');const args = process.argv.slice(2);const num = args[0];var optionsBD = { host: 'www.baidu.com', port: 80, path: '/s?wd=' + num, method: 'GET'};var options360 = { host: 'www.so.com', port: 443, path: '/s?q=' + num, method: 'GET'};if (!/^\d+$/.test(num)) { console.log(`參數(shù)錯誤,請輸入正確電話號碼或查詢平臺。\r\n例如:node phoneMark.js 15949566632`); process.exit(0);}function request(protocol, options, cb) { return new Promise((resolve, reject) => { var req = protocol.request(options, (res) => { var html = ''; res.setEncoding('utf8'); res.on('data', (chunk) => { html += chunk; }); res.on('end', () => { resolve(cb(html)); }); }); req.on('error', (err) => { reject(err); }); req.end(); });}Promise .all([request(http, optionsBD, AnalysizeByBD), request(https, options360, AnalysizeBy360)]) .then((vals) => { summary(vals); }, (err) => { console.log(err); });function summary(vals) { if ((/\d+/g).test(vals[0])) { console.log(`號碼${num}:為騷擾號碼,分別被百度、360標(biāo)記${vals[0]}、${vals[1]}次`); } else { console.log(`號碼${num}:${vals[0]}`); }}function AnalysizeByBD(html) { var $ = cheerio.load(html); var arr = $('.op_fraudphone_word').text().trim().replace(/\s+/g, "").match(/(\d+)/g) return arr ? arr[0] : $('.op_mobilephone_r').find('span').eq(1).text().replace(/\s*/g, "");}function AnalysizeBy360(html) { var $ = cheerio.load(html); return $('.mohe-tips').find('b').text();}