nodejs(2)-如何使用node來向其他服務器發(fā)送請求

##### URL模塊

這個模塊可以幫助我們解析url地址,從里面提取很多有用的內(nèi)容供我們使用;

假設這是一個url地址http://localhost:8080/a/b/c?a=1&b=2#abc,里面包含的部分:

```

protocol: 'http:',

host: 'localhost:8080',

port: '8080',

hostname: 'localhost',

hash: '#abc',

search: '?a=1&b=2',

query: 'a=1&b=2',

pathname: '/a/b/c',

path: '/a/b/c?a=1&b=2',

href: 'http://localhost:8080/a/b/c?a=1&b=2#abc'

```

url.parse(urlString[, parseQueryString[, slashesDenoteHost]])

會返回一個解析后的對象制圈,第一個參數(shù)為要解析的url地址,第二個參數(shù)為是否將query字符串解析成對象格式,第二個參數(shù)來控制在沒有協(xié)議的情況下淹接,是否解析域名等內(nèi)容

url.format(urlObject)

將一個url解析后的對象還原成一個url地址

url.resolve(from, to)

可以將我們兩段url解析成一個url地址

```

console.log(url.resolve('http://www.baidu.com','/api/index.html'))

//'http://www.baidu.com/api/index.html'

```

---

### queryString

可以將我們的queryString字符串(a=1&b=2&c=3)解析或反編譯

querystring.stringify(obj[, sep[, eq[, options]]]):

可以將一個對象(鍵值對)解析成一個querystring,第二個參數(shù)可以設置分割符號(&),第三個參數(shù)確定鍵值對之間的鏈接符號(=)

querystring.parse(str[, sep[, eq[, options]]])

可以將一個qs字符串解析成一個對象,后面的參數(shù)是按照某種規(guī)則去解析

querystring.escape(str),querystring.unescape(str)

可以將我們的中文解析成百分號編碼

```

console.log(qs.escape('北京'))//%E5%8C%97%E4%BA%AC

console.log(qs.unescape('%E5%8C%97%E4%BA%AC'))//北京

```

---

#### http小爬蟲

##### 首先我們先研究一下什么是SEO

Search Engine Optimization 搜索引擎優(yōu)化叛溢,是一種技術塑悼,目的是提高網(wǎng)頁在搜索引擎的排行

如何能提高排行:

1. 給百度花錢

2. 找專業(yè)的優(yōu)化團隊

3. 開發(fā)過程中注意優(yōu)化,例如楷掉,在不影響頁面結構的情況下多使用語義化標簽厢蒜!img的title等也需要設置,title標簽必須有,通過meta標簽設置description斑鸦、keywords愕贡、author;不需要使用ajax獲取的數(shù)據(jù)就不要獲取了巷屿,盡量可以使用服務端渲染數(shù)據(jù)的方式

---

利用http.get方法去獲取到某網(wǎng)址的html文件內(nèi)容固以,然后利用cheerio工具進行關鍵內(nèi)容的提取

1. 獲取到 https://www.lagou.com這個接口的數(shù)據(jù)(其實就是拉鉤的首頁文件)

因為http、https模塊可以向其他的服務器發(fā)送請求攒庵,依靠的是request方法或者其子方法:get嘴纺、post;

```

let target = 'https://www.lagou.com'

const https = require('https')

//發(fā)送一個get請求,res是一個返回的對象浓冒,里面并沒有直接包含數(shù)據(jù)栽渴,需要使用data事件來接收返回的數(shù)據(jù)

//且每次返回的只是一個片段,所以會觸發(fā)多次稳懒,因為可能請求到的數(shù)據(jù)量特大闲擦,如果一次性返回的話可能導致服務器崩潰,所以Node采取事件的方式多次返回

https.get(target, function(res) {

let result = ''

res.on("data",(chunk)=>{

result += chunk

})

res.on("end",()=>{//當接收完后觸發(fā)

//在這里就可以處理數(shù)據(jù)result

})

})

```

2. 爬取其上面的一級场梆、二級標題的內(nèi)容

因為獲取到的是一個大的html格式的字符串墅冷,所以想要爬取其中某些標簽的內(nèi)容不能直接使用jq,用正則匹配又有些繁瑣或油,所以使用cheerio工具寞忿,這個工具可以在服務端將html格式的字符串進行編譯后返回一個$對象,這樣就可以像使用JQ一樣去操作了

```

const cheerio = require("cheerio")

let spideContent = (result,callback)=>{

let $ = cheerio.load(result)

let menus = []

$(".menu_main").each(function (i) {

let title = $(this).find('h2').text().trim()

let navs = Array.prototype.slice.call($(this).find('a')).map((item)=>{

return $(item).text()

})

menus.push({title,navs})

})

callback(menus)//通過回調(diào)函數(shù)來處理解析后的數(shù)據(jù)

}

```

3.? 再把爬取出的內(nèi)容存到一個文件里

```

spideContent(result,(menus)=>{

fs.writeFileSync('./lagou.json',JSON.stringify(menus))

})

```

##### JS小知識擴展

如何將偽數(shù)組轉(zhuǎn)換成真正的數(shù)組顶岸?

1. 常見的偽數(shù)組都有哪些腔彰?arguments、通過document.getElements..獲取到的內(nèi)容辖佣;

2. 偽數(shù)組有什么特點霹抛,具有l(wèi)ength屬性,也是一個一個的元素組成的卷谈,但是構造器不是Array杯拐,不能使用數(shù)組的方法

3. 轉(zhuǎn)換為真正數(shù)組的方法:

通過遍歷將偽數(shù)組里元素放入到一個新的數(shù)組里

```

let arg = arguments//這就是一個典型的偽數(shù)組

let arr = []

for (var i = 0; i < arg.length; i++) {

arr.push(arg[i])

}

console.log(arr)

```

通過call改變數(shù)組slice方法里的this指向

因為我想要讓偽數(shù)組也能使用數(shù)組的方法,為什么偽數(shù)組就不能使用數(shù)組方法世蔗,為什么數(shù)組就能使用push方法了

一個數(shù)組都是由它的構造器實例化出來的端逼,var a = []//這是js的語法糖;正規(guī)的用法:var a = new Array()

因為Array是一個構造函數(shù)凸郑,每一個構造函數(shù)都有原型,且構造函數(shù)構造出來的實例可以使用原型上的方法裳食,也就是說因為Array的原型上有一些方法,所以每一個數(shù)組都可以使用這些push等等的方法

因為偽數(shù)組的構造器不是Array芙沥,當然不能使用Array原型上的push方法

現(xiàn)在數(shù)組有一個方法slice,這個方法每次都會返回一個新數(shù)組,如果不傳參數(shù)的話而昨,返回的新數(shù)組的元素和原數(shù)組的元素是一模一樣的

如果偽數(shù)組也能執(zhí)行這個slice方法的話救氯,那么是不是就會返回一個新的真正的數(shù)組,并且元素一樣歌憨,但是不能直接執(zhí)行

所以我們使用偷梁換柱的方法着憨,讓一個真正的數(shù)據(jù),或者直接從Array.prototype上執(zhí)行slice方法务嫡,但是在執(zhí)行的時候通過call來將里面的this換成咱們的偽數(shù)組甲抖,這樣的話,就會返回一個元素和偽數(shù)組元素一樣的真正數(shù)組了

```

let arr = [].slice.call(arg) //Array.prototype.slice.call(arg)

```

---

##### requestGet/requestPost

1. 通過request來get數(shù)據(jù)(請求的是豆瓣電影的api):

```

let target = 'http://api.douban.com/v2/movie/in_theaters'

const http = require('http')

const url_info = require('url').parse(target,true)

//定義配置選項

let options = {

hostname: url_info.hostname,//要請求的接口的域名

port: url_info.port||80,

path: url_info.pathname,

method: 'GET'

};

//創(chuàng)建一個請求的對象

var req = http.request(options, function(res) {//回調(diào)函數(shù)能接收到響應對象

//狀態(tài)碼 res.statusCode

//響應頭 res.headers

res.setEncoding('utf8');//設置字符編碼

let result = ''

res.on('data', function (chunk) {//通過data事件來接收數(shù)據(jù)

result+=chunk

});

res.on('end', function () {//接收完成后觸發(fā)

fs.writeFileSync('./movie.json',result)

});

});

//綁定error事件心铃,如果出錯會執(zhí)行

req.on('error', function(e) {

console.log('problem with request: ' + e.message);

});

//標識請求完成

req.end();

```

2. 通過request的post方法來請求:

注意准谚,get方法發(fā)送的參數(shù)是拼接在url上的,post是以formdata存在的,但是發(fā)送過去的必須都得是字符串格式

大部分步驟基本一樣去扣,但是需要注意的是柱衔,post請求的時候需要設置請求頭里的Content-Length,需要通過req.write方法來寫入請求信息

```

const target = 'http://post.baibaoyun.com/api/0a953068ff01781ce22c0822c075018c'

const qs = require('querystring')

const http = require('http')

let url_info = require('url').parse(target)

//定義好要發(fā)送的數(shù)據(jù)

var postData = qs.stringify({

'a':'text1',

'b':'text2'

});//必須變成這樣的格式 'a=text1&b=text2'

var options = {

hostname: url_info.hostname,

port: url_info.port||80,

path: url_info.pathname,

method: 'POST',

headers: {

'Content-Type': 'application/x-www-form-urlencoded',

'Content-Length': postData.length//post發(fā)送的時候需要將請求頭的Content-Length設置為發(fā)送數(shù)據(jù)的leng

}

};

var req = http.request(options, function(res) {

res.setEncoding('utf8');

let result = ''

res.on('data', function (chunk) {

result+=chunk

});

res.on('end', function () {

console.log(result)

});

});

req.on('error', function(e) {

console.log('problem with request: ' + e.message);

});

//寫入請求發(fā)送的數(shù)據(jù)

req.write(postData);

req.end();

```

###### 小作業(yè)

總結POST和GET的區(qū)別,每位同學都寫一個md文檔

---

##### fileStystem模塊

后端語言都有操作文件系統(tǒng)的能力愉棱,在nodejs里我們依靠的是fs模塊

每種操作的方法基本都有同異步的兩種不同方法

1.查看文件信息(多用來判斷文件是否存在)exists

```

var fs=require('fs');

//異步查詢文件信息

fs.stat("../sources/temp.txt",(err,data)=>{

if(err){

console.log(err);

}else{

console.log(data)

//判斷是否是文件

console.log(`文件:${data.isFile()}`)

//判斷是否是路徑

console.log(`目錄:${data.isDirectory()}`)

}

})

//同步查詢

//fs.statSync("../sources/temp.txt")

console.log(1)

```

2.創(chuàng)建一個目錄

```

//創(chuàng)建一個目錄唆铐,如果目錄已存在的話就會返回錯誤信息

fs.mkdir("logs",function(err){

if(err){

console.log(err);

}else{

console.log('success');

}

})

```

3.寫入文件

```

//給文件寫內(nèi)容,當文件不存在會創(chuàng)建一個文件奔滑,第二個參數(shù)為寫入的內(nèi)容,每次寫入都會覆蓋

fs.writeFile('logs/hello.log','hello everyone\n',function(err){

if(err){

console.log(err);

}else{

console.log('success')

}

})

//給文件中追加內(nèi)容

fs.appendFile("logs/hello.log",'hello world\n',function(err){

if(err){

console.log(err);

}else{

console.log('success')

}

})

```

4.讀取文件內(nèi)容

```

//讀取文件內(nèi)容的方法艾岂,第二個參數(shù)可選,為讀取的編碼格式

fs.readFile("logs/hello.log",'utf-8',function(err,data){

if(err){

console.log(err);

}else{

console.log(data)

}

})

```

5.讀取目錄內(nèi)容

```

//讀取目錄內(nèi)容朋其,返回一個數(shù)組

fs.readdir("logs",function(err,files){

if(err){

console.log(err);

}else{

console.log(files)

}

})

```

6.文件重命名

```

//重命名方法

fs.rename("logs/hello.log","logs/world.log",function(err){

if(err){

console.log(err)

}else{

console.log('success')

}

})

```

7.刪除目錄王浴、文件

fs.rmdir可以刪除目錄但是,必須是空目錄令宿,fs.unlink可以刪除文件叼耙,如果我們要刪除一個目錄及它下面的文件或子目錄的話,我們需要先讀取出來粒没,刪除完成后再進行根目錄的刪除

8.小練習:創(chuàng)建一個copy復制文件的函數(shù)

```

const fs = require('fs')

const _path = require('path')

let copy = (path,target)=>{

fs.stat(path,(err)=>{

if(err){

console.log('要復制的文件不存在')

}else{

let content = fs.readFileSync(path)

fs.writeFile(target+'/'+_path.basename(path).replace('.','-副本.'),content,(err)=>{

if(err){console.log('目標目錄不存在')}else{

console.log('success')

}

})

}

})

}

copy('./sources/hello.txt','./sources/a')

```

9.fs-extra模塊

這是一個第三方的fs模塊筛婉,需要下載? npm install fs-extra

fs模塊上的方法它都有,并且還封裝了一些很好用的方法癞松,比如:copy爽撒、remove..

[文檔地址](https://www.npmjs.com/package/fs-extra)

###### ES6小知識

Object.assign方法可以將一些對象中的屬性和方法擴展到某一個對象上

```

var a = {y:2}

var b ={x:1}

var c = {z:3}

Object.assign(a,b,c)

console.log(a)//{x:1,y:2,z:3}

```

---

最后編輯于
?著作權歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市响蓉,隨后出現(xiàn)的幾起案子硕勿,更是在濱河造成了極大的恐慌,老刑警劉巖枫甲,帶你破解...
    沈念sama閱讀 206,013評論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件源武,死亡現(xiàn)場離奇詭異扼褪,居然都是意外死亡,警方通過查閱死者的電腦和手機粱栖,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,205評論 2 382
  • 文/潘曉璐 我一進店門话浇,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人闹究,你說我怎么就攤上這事幔崖。” “怎么了渣淤?”我有些...
    開封第一講書人閱讀 152,370評論 0 342
  • 文/不壞的土叔 我叫張陵赏寇,是天一觀的道長。 經(jīng)常有香客問我价认,道長嗅定,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 55,168評論 1 278
  • 正文 為了忘掉前任刻伊,我火速辦了婚禮露戒,結果婚禮上,老公的妹妹穿的比我還像新娘捶箱。我一直安慰自己智什,他們只是感情好,可當我...
    茶點故事閱讀 64,153評論 5 371
  • 文/花漫 我一把揭開白布丁屎。 她就那樣靜靜地躺著荠锭,像睡著了一般。 火紅的嫁衣襯著肌膚如雪晨川。 梳的紋絲不亂的頭發(fā)上证九,一...
    開封第一講書人閱讀 48,954評論 1 283
  • 那天,我揣著相機與錄音共虑,去河邊找鬼愧怜。 笑死,一個胖子當著我的面吹牛妈拌,可吹牛的內(nèi)容都是我干的拥坛。 我是一名探鬼主播,決...
    沈念sama閱讀 38,271評論 3 399
  • 文/蒼蘭香墨 我猛地睜開眼尘分,長吁一口氣:“原來是場噩夢啊……” “哼猜惋!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起培愁,我...
    開封第一講書人閱讀 36,916評論 0 259
  • 序言:老撾萬榮一對情侶失蹤著摔,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后定续,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體谍咆,經(jīng)...
    沈念sama閱讀 43,382評論 1 300
  • 正文 獨居荒郊野嶺守林人離奇死亡禾锤,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 35,877評論 2 323
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了卧波。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片时肿。...
    茶點故事閱讀 37,989評論 1 333
  • 序言:一個原本活蹦亂跳的男人離奇死亡庇茫,死狀恐怖港粱,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情旦签,我是刑警寧澤查坪,帶...
    沈念sama閱讀 33,624評論 4 322
  • 正文 年R本政府宣布,位于F島的核電站宁炫,受9級特大地震影響偿曙,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜羔巢,卻給世界環(huán)境...
    茶點故事閱讀 39,209評論 3 307
  • 文/蒙蒙 一望忆、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧竿秆,春花似錦启摄、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,199評論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至匪燕,卻和暖如春蕾羊,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背帽驯。 一陣腳步聲響...
    開封第一講書人閱讀 31,418評論 1 260
  • 我被黑心中介騙來泰國打工龟再, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人尼变。 一個月前我還...
    沈念sama閱讀 45,401評論 2 352
  • 正文 我出身青樓利凑,卻偏偏與公主長得像,于是被迫代替她去往敵國和親享甸。 傳聞我的和親對象是個殘疾皇子截碴,可洞房花燭夜當晚...
    茶點故事閱讀 42,700評論 2 345

推薦閱讀更多精彩內(nèi)容