Phantomjs 使用說明

phantomjs實現(xiàn)了一個無界面的webkit瀏覽器尤勋。雖然沒有界面,但dom渲染茵宪、js運行最冰、網(wǎng)絡(luò)訪問、canvas/svg繪制等功能都很完備稀火,在頁面抓取锌奴、頁面輸出、自動化測試等方面有廣泛的應(yīng)用憾股。

安裝

下載phantomjs( 官方下載 鹿蜀,下載失敗請訪問 另一個下載點 )。解壓到任意目錄服球,并將包含phantomjs.exe的目錄添加到系統(tǒng)路徑茴恰。

如果要借助phantomjs進行無頭測試,請參考各個測試框架的說明斩熊,或者參考phantomjs的官方文檔: http://phantomjs.org/headless-testing.html 往枣。

使用說明

簡單示例

// test.js
var page = require('webpage').create(),
	system = require('system'),
	address;
if (system.args.length === 1) {
	phantom.exit(1);
} else {
	address = system.args[1];
	page.open(address, function (status) {
		console.log(page.content);
		phantom.exit();
	});
}

運行:

phantomjs ./test.js http://baidu.com

這個例子簡單地展示了通過phanton訪問baidu.com,并輸入html內(nèi)容粉渠。使用方式就像使用node運行js代碼一樣分冈。在phantom運行時,它會向當前代碼運行環(huán)境注入phantom對象霸株。如上面代碼中雕沉,通過phantom對象控制程序終結(jié)。示例中其他代碼的含義以及更多深入的用法去件,將在下文中展開坡椒。


window對象

在使用phantom時,我首先關(guān)注的是DOM和BOM接口尤溜。不過這不是一個問題倔叼,看了下面的代碼就能了解:

// test.js
console.log(window === this);
phantom.exit();

運行:

phantomjs ./test.js

結(jié)果為 true 。也就是說宫莱,就像瀏覽器環(huán)境一樣丈攒,我們的代碼運行在window環(huán)境下,可以很方便地進行DOM方面的操作。

注:如果使用web page模塊打開頁面巡验,則請不要在此window對象下進行任何DOM相關(guān)的操作识椰,因為這個window并不是page對象內(nèi)的window。如果想要執(zhí)行dom相關(guān)操作深碱,請參閱 page.evaluate() 部分腹鹉。


phantom對象

之前的例子中我們已經(jīng)初步認識了phantom對象。它的功能是定義和控制phantom運行環(huán)境的參數(shù)和流程敷硅。關(guān)鍵的API有:

phantom.args String[]

獲取傳給本JS程序的參數(shù)功咒,需要與 system.args 進行區(qū)分(system模塊詳見下文),后者表示傳給phantomjs引擎的參數(shù)绞蹦。例如 phantomjs ./test.js http://baidu.com 這句語句鸦致,通過 phantom.args 盆犁,我們能得到的參數(shù)列表為 ["http://baidu.com"] 冗懦,而通過 system.args 則得到 ["./test.js", "http://baidu.com"] 這樣的參數(shù)列表离福。差異就在于是否包含當前腳本名稱。不過 phantom.scriptName 這個API提供了獲取腳本名稱的功能澡屡。

phantom.cookies Object[]

獲取或設(shè)置cookies猿挚,不過對于設(shè)置建議使用其他的API完成。同時相關(guān)的API還有:

phantom.addCookie(Object) Boolean:添加cookie值

phantom.deleteCookie(cookieName) Boolean:刪除指定Cookie值

phantom.clearCookies() :清空所有的cookie

phantom.cookiesEnabled Boolean:獲取或設(shè)置是否支持cookie

phantom.injectJs(fileName) Boolean:

把指定的外部JS文件注入到當前環(huán)境驶鹉。執(zhí)行這個方法時绩蜻,phantomjs首先會從當前目錄檢索此文件,如果找不到室埋,則再到 phantom.libraryPath 指定的路徑尋找办绝。 phantom.libraryPath 這個API基本上就是為 phantom.injectJs() 服務(wù)的。

phantom.onError

當頁面存在js錯誤姚淆,且沒有被 page.onError 處理孕蝉,則會被此handler捕獲。下面是使用此API的一個例子腌逢。由于phantom環(huán)境下代碼調(diào)試很困難降淮,了解這些錯誤捕獲的API也許會對我們的實際使用有所幫助。

phantom.onError = function(msg, trace) {
   var msgStack = ['PHANTOM ERROR: ' + msg];
   if (trace && trace.length) {
     msgStack.push('TRACE:');
     trace.forEach(function(t) {
       msgStack.push(' -> ' + (t.file || t.sourceURL) + ': ' + t.line + (t.function ? ' (in function ' + t.function +')' : ''));
     });
   }
   console.error(msgStack.join('\n'));
   phantom.exit(1);
 };

phantom.exit(returnValue)

這個API已經(jīng)見過多次了上忍,它的作用是退出程序骤肛,可以設(shè)置一個退出代碼纳本,默認是0窍蓝。


web page 模塊

web page模塊的功能是處理具體的頁面。使用時需要引入模塊繁成,并創(chuàng)建實例:

var webPage = require('webpage');
var page = webPage.create();

本文中不經(jīng)說明吓笙, page 指代 require("webpage").create() 的實例。

page.cookies Object[]

與上文中的 phantom.cookies 類似巾腕,表示本url下的cookie的讀取面睛。同樣類似的API還有 addCookie() 絮蒿、 deleteCookie()clearCookies() 叁鉴。

頁面內(nèi)容相關(guān)的API

page.content String:獲取或設(shè)置當前頁面的html土涝。

page.plainText String:這是一個只讀屬性,獲取頁面去除html標記的文本(考慮 $.text() )幌墓。

page.url String:只讀但壮,獲取當前頁面的url。

page.setContent() :允許修改 page.contentpage.url 內(nèi)容常侣,會觸發(fā)reload蜡饵。

page.settings Object

對于當前頁面的一些配置項。此API必須在 page.open() 調(diào)用之前設(shè)置胳施,否則不會起作用溯祸。以下是配置項: * javascriptEnabled 默認 true :是否執(zhí)行頁面內(nèi)的javascript

loadImages 默認 true :是否載入圖片

userAgent :傳遞給服務(wù)器的userAgent字符串

userName :用于http訪問授權(quán)的用戶名

password :用于http訪問授權(quán)的密碼

XSSAuditingEnabled 默認 false :是否監(jiān)控跨域請求

resourceTimeout 單位 ms :定義資源請求的超時時間。如果設(shè)置了此項舞肆,則頁面中如果有任何資源超過此時限未請求成功焦辅,則頁面其他部分也會停止請求,并觸發(fā) onResourceTimeout() 事件處理椿胯。

page.customHeaders Object

phantom允許在請求時在http請求頭部添加額外信息氨鹏,此設(shè)置項對這個page里面所有的請求都生效(包含頁面和其他資源的請求)。添加的信息并沒有限制压状,但如果設(shè)置 User-Agent 的值仆抵,那么這個值會覆蓋掉 page.settings 里的設(shè)置值。示例:

page.customHeaders = {
   "X-Test": "foo",
   "DNT": "1"
 };

page.libraryPath String

phantom.libraryPath 類似种冬,page對象也支持設(shè)置js文件路徑镣丑,同時可以通過相應(yīng)的 page.injectJs() 方法注入javascript文件。除了 page.injectJs() 方法外娱两,還有 page.includeJs() 也可以加入javascript文件莺匠。它們的區(qū)別在于, page.injectJs() 不強求此文件能訪問得到十兢,即使是一個不可訪問的資源也可以趣竣。

page.navigationLocked Boolean 默認 fasle

設(shè)置是否允許離開當前頁面,默認是允許旱物。

page.open()

此方法用于打開一個網(wǎng)頁遥缕,是一個很重要的API,它有三種調(diào)用形式:

open(url, callback)

open(url, method, callback)

open(url, method, data, callback)

聯(lián)想一下 $.ajax() 宵呛,可以更好理解這個API单匣。對于這些參數(shù),需要單獨闡述的是 callbackcallback() 會在頁面載入完成后調(diào)用户秤,由 page.onLoadFinished 調(diào)用(時機晚于 page.onLoadFinished )码秉。這個 callback 會接受一個參數(shù) status ,可能值為 "success""fail" 鸡号,指示頁面是否加載成功转砖。示例可以參考“簡單示例”一節(jié)的例子。

page.close()

page.open() 對應(yīng)鲸伴,調(diào)用 page.close() 之后堪藐,會釋放page所占用的內(nèi)存,我們不可以在此之后再調(diào)用page實例挑围。在實際的操作中礁竞,調(diào)用此方法并不會完成清空所占內(nèi)存;javascript的垃圾回收機制也不會回收page實例杉辙。但在實際使用中模捂,常常會遇到將一個page實例反復(fù)open的情況。在一個頁面用完后蜘矢,記得一定要執(zhí)行 page.close() 狂男,這樣在下一次open的時候,才不會重復(fù)分配堆椘犯梗空間岖食。

page.evaluate(fn, [param])

對于page打開的頁面,往往需要與其進行一些交互舞吭。 page.evaluate() 提供了在page打開頁面的上下文(下文直接用page上下文指代)執(zhí)行function的功能(類比Chrome開發(fā)者工具的控制臺)泡垃。如下例:

page.open('http://m.bing.com', function(status) {
   var title = page.evaluate(function(s) {
     return document.querySelector(s).innerText;
   }, 'title');
   console.log(title);
   phantom.exit();
 });

在這個例子中, page.evaluate() 接受兩個參數(shù)羡鸥,第一個是必需的蔑穴,表示需要在page上下文運行的函數(shù) fn ;第二個是可選的惧浴,表示需要傳給 fn 的參數(shù) param 存和。 fn 允許有一個返回值 return ,并且此返回值最終作為 page.evaluate() 的返回值衷旅。這邊對于剛剛命名的 paramreturn 有一些額外的說明和注意事項捐腿。對于整個phantom進程而言, page.evaluate() 是跑在一個沙盒中柿顶, fn 無法訪問一切phantom域中的變量茄袖;同樣 page.evaluate() 方法外部也不應(yīng)該嘗試訪問page上下文中的內(nèi)容。那么如果兩個作用域需要交換一些數(shù)據(jù)九串,只能依靠 paramreturn 绞佩。不過限制很大寺鸥, paramreturn 必須為能夠轉(zhuǎn)化為JSON字符串猪钮,換言之品山,只能是基本數(shù)據(jù)類型或者簡單對象,像DOM 節(jié)點烤低、$對象肘交、function、閉包等就無能為力了扑馁。

這個方法是同步的涯呻,如果執(zhí)行的內(nèi)容對后續(xù)操作不具備前置性,可以嘗試異步方法以提高性能: page.evaluateAsync() 腻要。

page.render(filename)

page.render() 能夠把當前頁面渲染成圖片并輸出到指定文件中复罐。輸出的文件格式由傳入的文件擴展名決定,目前支持 PNG 雄家、 JPEG 效诅、 GIFPDF 趟济。

var page = require('webpage').create();
page.open('http://github.com/', function() {
  page.render('github.png');
  phantom.exit();
});

還有其他一些API會對 page.render() 產(chǎn)生影響乱投,如:

page.zoomFactor Number: 設(shè)置縮放比率

page.clipRect Object:設(shè)置輸出的矩形區(qū)域,例如:

page.clipRect = {
    top: 14,
    left: 3,
    width: 400,
    height: 300
  };

還有一些頁面設(shè)置參數(shù)顷编,如果紙張大小戚炫,側(cè)邊距等,在此不詳述媳纬。web page也支持輸出圖片base64格式的字符串双肤,API為 page.renderBase64() ,也不再詳述钮惠。

page.sendEvent()

為了交互的需要(測試的需要)杨伙,phantom允許通過代碼模擬一些交互事件(注意與DOM事件的區(qū)分)。

鼠標事件:

API: sendEvent(mouseEventType[, mouseX, mouseY, button='left'])

mouseEventtype 可能的取值為: 'mouseup' 萌腿、 'mousedown' 限匣、 'mousemove''doubleclick''click' 毁菱,這個參數(shù)為必須的米死。

后兩個參數(shù)為鼠標事件的坐標位置。最后一個參數(shù)為鼠標按鍵贮庞,只對需要按鍵的事件有效峦筒,默認為 'left' ,可能值為 'right' 窗慎、 'left' 物喷、 'middle' 卤材。

鍵盤事件:

API: sendEvent(keyboardEventType, keyOrKeys, [null, null, modifier])

keyboardEventType 可能的取值為 'keyup''keydown' 峦失、 'keypress' 扇丛,第2個參數(shù)傳入一個鍵值或一個字符串。鍵值可以通過 page.event.key 來查詢調(diào)用尉辑。第三和第四個參數(shù)無效帆精,第五個參數(shù)表示同時按下的修飾鍵。取值情況如下:

: 未使用修飾鍵

0x02000000

: Shift鍵被按下

0x04000000

: Ctrl鍵被按下

0x08000000

: Alt鍵被按下

看一個示例:

page.sendEvent('keypress', page.event.key.A, null, null, 0x02000000 | 0x08000000);

page.switchToFrame(frameName/framePosition)

默認page對應(yīng)的是frame隧魄,如果一個頁面中還有其他frame卓练,則可以通過此方法切換page對應(yīng)的frame。其他類似的方法還有 switchToChildFrame() 购啄、 switchToParentFrame() 襟企、 switchToFocusedFrame()switchToMainFrame() 等狮含,不再贅述顽悼。

page.uploadFile(selector, file)

頁面中常常會有上傳文件的操作,但phantom沒有界面辉川,因而也就沒有辦法選擇文件上傳表蝙,通過此方法可以模擬文件上傳操作。示例如下:

page.uploadFile('input[name=image]', '/path/to/some/photo.jpg');

一些事件處理接口

page.onAlert :phantom沒有界面乓旗,所以也就不能處理alert窗口府蛇,但可以通過此接口捕獲到alert。

page.onPrompt :類似的屿愚,phantom不能處理prompt窗口汇跨,通過這個接口可以捕獲prompt。

page.onConfirm :類似的妆距,phantom不能處理confirm窗口穷遂,通過這個接口可以捕獲confirm。

page.onConsoleMessage :類似的娱据,phantom不能顯示console窗口蚪黑,通過這個接口可以捕獲console消息。

var webPage = require('webpage');
  var page = webPage.create();
  page.onAlert = function(msg) {
    console.log('ALERT: ' + msg);
  };
  page.onPrompt = function(msg, defaultVal) {
    if (msg === "What's your name?") {
      return 'PhantomJS';
    }
    // 返回值就是prompt得到的值
    return defaultVal;
  };
  page.onConfirm = function(msg) {
    console.log('CONFIRM: ' + msg);
    // 返回true相當于點擊“確定”中剩,返回false相當于點擊“取消”
    return true;
  };
  page.onConsoleMessage = function(msg, lineNum, sourceId) {
    console.log('CONSOLE: ' + msg + ' (from line #' + lineNum + ' in "' + sourceId + '")');
  };

page.onInitialized :在page創(chuàng)建后觸發(fā)忌穿。

page.onUrlChanged :在url發(fā)生變化時觸發(fā)。它接受新的url作為參數(shù)结啼。首次加載頁面掠剑, page.onUrlChanged 是在 page.onInitialized 之后觸發(fā)。

page.onNavigationRequested :如果在 page.navigationLocked 中允許頁面跳轉(zhuǎn)郊愧,此接口才會有意義(參見 page.navigationLocked )朴译。它接受4個參數(shù)井佑,先看示例:

page.onNavigationRequested = function(url, type, willNavigate, main) {
    console.log('Trying to navigate to: ' + url);
    console.log('Caused by: ' + type);
    console.log('Will actually navigate: ' + willNavigate);
    console.log('Sent from the page\'s main frame: ' + main);
  }

url

表示要跳轉(zhuǎn)到的url

type

表示產(chǎn)生跳轉(zhuǎn)的原因,可能值有

'Undefined'

眠寿、

'LinkClicked'

躬翁、

'FormSubmitted'

'BackOrForward'

澜公、

'Reload'

姆另、

'FormResubmitted'

喇肋、

'Other'

willNavigate

表示是否會跳轉(zhuǎn)坟乾,由

page.navigationLocked

控制

main

表示發(fā)生跳轉(zhuǎn)的是否是主frame,如果是主frame則為true蝶防,如果為其他frame則為false

page.onLoadStarted :在開始載入資源時觸發(fā)甚侣。

page.onLoadFinished :頁面所有資源載入完成后觸發(fā)。其實與 page.open() 的回調(diào)函數(shù)等價间学。它接受一個參數(shù) status 殷费,表示加載是否成功。參見 page.open() 低葫。

page.onClosing :當在phantom域調(diào)用 page.close() 或page上下文調(diào)用 window.close() 時觸發(fā)详羡。

page.onError : 此接口捕獲所有page上下文發(fā)生的javascript錯誤。參數(shù)是錯誤信息和調(diào)用堆棧嘿悬,參見 phantom.onError 实柠。如果page不處理錯誤,那么這些錯誤會冒泡到phantom的onError處理器善涨。

page.onCreate :當page創(chuàng)建子窗口時觸發(fā)窒盐,例如在page上下文中使用 window.open ,但是子窗口再創(chuàng)建子窗口不會觸發(fā)此事件钢拧。

page.onResourceRequested :當頁面請求一個資源時觸發(fā)的事件蟹漓,它接受兩個參數(shù),第一個參數(shù)是 requestData 對象源内,它有如下屬性:

id

: 資源請求編號

method

: http請求方法葡粒,get/post等

url

:請求的URL

time

: 一個Date object,包含響應(yīng)接收的時間

headers

: http頭部的信息列表

第二個參數(shù)是 networkRequest 實例膜钓,它包含3個方法:

* `abort()`:中斷當前的請求嗽交。這樣做會觸發(fā)onResourceError
* `changeUrl(url)`:改變當前請求的目標url
* `setHeader(key, value)`:修改/添加http頭部信息

page.onResourceReceived :當一個資源請求的響應(yīng)接收到后觸發(fā)此事件,它接受一個 response 對象呻此,這個對象有如下屬性:

id

: 資源請求編號

url

:請求的URL

time

: 一個Date object轮纫,包含響應(yīng)接收的時間

headers

: http頭部的信息列表

bodySize

: 已接收到的數(shù)據(jù)大小(全部數(shù)據(jù)或已接收的部分數(shù)據(jù))

contentType

: 指定的內(nèi)容類型

redirectURL

: 如果是一個重定向響應(yīng)焚鲜,那么此處是重定向到的url

stage

: “start”/ “end”

status

: http狀態(tài)碼掌唾,如:200

statusText

: http狀態(tài)描述放前,如:OK

page.onResourceError :當資源加載失敗時,觸發(fā)此事件糯彬。它接收一個 resourceError 對象凭语,這個對象有如下屬性:

id

:資源請求的編號

url

:請求的URL

errorCode

:錯誤代碼

errorString

:錯誤信息

可參考如下示例:

page.onResourceError = function(resourceError) {
  console.log('Unable to load resource (#' + resourceError.id + 'URL:' + resourceError.url + ')');
  console.log('Error code: ' + resourceError.errorCode + '. Description: ' + resourceError.errorString);
};

page.onResourceTimeout

:在講

page.settings

時曾經(jīng)提到過這個事件。如果設(shè)置了

page.settings.resourceTimeout

撩扒,并且資源在這個時間內(nèi)沒有載入完成似扔,則會觸發(fā)此事件,它接受一個

request

對象搓谆,這個對象包含如下屬性:

id

: 資源請求編號

method

: http請求方法炒辉,get/post等

url

:請求的URL

time

: 一個Date object,包含響應(yīng)接收的時間

headers

: http頭部的信息列表

errorCode

:錯誤代碼

errorString

:錯誤信息


Child Process模塊

通過Child Process模塊泉手,我們能創(chuàng)建子進程黔寇,借助 stdinstdout 斩萌、 stderr 來實現(xiàn)進程間通信(很C++)缝裤。使用子進程能夠做很多事情,如打印颊郎、發(fā)郵件憋飞、調(diào)用腳本或其他程序(不局限于javascript)。

要使用Child Process模塊姆吭,我們需要在代碼中添加 require("child_process") 榛做。

以下內(nèi)容缺乏文檔支持,并未經(jīng)過充分測試猾编,可能存在一定的理解偏差瘤睹。這部分功能是極有用的,希望在項目中使用的時候注意測試答倡。

Child Process模塊本身應(yīng)該也并完全開發(fā)完全轰传。 spawn()execFile() 可用瘪撇, exec()fork() 尚未實現(xiàn)获茬。

spawn(command, [args], [options])

最基本的創(chuàng)建進程的方法。前兩個參數(shù)比較重要倔既,例如現(xiàn)在想從phantom進程中運行一段nodejs腳本恕曲,腳本路徑為 “main.js” ,這個腳本接受一個參數(shù)渤涌,假定為 “helloworld” 佩谣,那么如果想得到這段腳本的運行結(jié)果應(yīng)該怎么做呢?參考下面的腳本:

var spawn = require("child_process").spawn;
 child = spawn('node', ['main.js', 'helloworld']);
 child.stdout.on("data", function (data) {
	 console.log("spawnSTDOUT:", JSON.stringify(data))
 });
 child.stderr.on("data", function (data) {
	 console.log("spawnSTDERR:", JSON.stringify(data))
 });
 child.on("exit", function (code) {
	 console.log("spawnEXIT:", code)
 });
 setTimeout(function () {
	 phantom.exit(0)
 }, 2000);

其實 spawn() 方法沒什么神秘的实蓬,它就是運行第一個參數(shù)表示的命令茸俭,第二個參數(shù)就是這個命令的參數(shù)列表吊履。所以如果要開啟一個新的phantom進程,第一個參數(shù)為 phantom 就行调鬓。同樣的道理艇炎,指定好程序的路徑或者是腳本語言解釋器的路徑,通過這個方法可以做的事情很多腾窝。 比較不方便的是缀踪,進程間的通信只能通過 stdinstdout 虹脯、 stderr 來完成驴娃,調(diào)用 spawn() 方法后,還需要對這些交互信息進行監(jiān)聽归形,上面的例子中演示了監(jiān)聽 stdoutstderr 的方法托慨。

execFile(cmd, args, opts, cb)

就像剛剛說的鼻由, spawn() 方法稍微感覺有點麻煩暇榴,使用 execFile() 能夠稍稍簡化上面的代碼。 execFile() 的前三個參數(shù)與 spawn() 的三個參數(shù)完全一樣蕉世,不同的是它多了一個 cb 回調(diào)函數(shù)蔼紧,看一個例子就知道這個回調(diào)函數(shù)有什么用了:

var execFile = require("child_process").execFile;
 child = execFile('node', ['main.js', 'helloworld'], null,
	 function (err, stdout, stderr) {
		 console.log("execFileSTDOUT:", JSON.stringify(stdout))
		 console.log("execFileSTDERR:", JSON.stringify(stderr))
	 });
 setTimeout(function () {
	 phantom.exit(0)
 }, 2000);

execFile() 中,對 stdout 狠轻、 stderr 的監(jiān)聽做了封裝奸例,簡化了我們的代碼,不過功能上與 spawn() 并無區(qū)別向楼。


file system模塊

雖然與node.js中文件系統(tǒng)模塊名稱和調(diào)用方法( require("fs") )一樣查吊,但不得不說,phantom的文件系統(tǒng)模塊總體是比較簡單的湖蜕,API不多但夠用逻卖,API也不同于node.js的異步回調(diào)風格,而是采用stream+同步的風格昭抒,濃濃的C++風味评也。在使用的時間請一定要注意與node.js的文件系統(tǒng)模塊做區(qū)分。

fs.open(path, mode/opts) File

open() 方法接受兩個參數(shù)灭返,第一個參數(shù)是要打開的文件路徑盗迟,第二個參數(shù)后面還會見到,這里統(tǒng)一說明熙含。如果是字符串罚缕,則代表文件打開的模式,可選的有 'r' 怎静、 'w' 邮弹、 'a/+' 喂饥、 'b' (read時僅支持 'b' );如果是一個對象肠鲫,則表示配置項员帮,一共有兩個配置項,分別是 modecharset 导饲, mode 就是剛剛提到的打開模式捞高, charset 表示文件的編碼類型。參閱下面的示例:

var fs = require("fs");
 var file = fs.open("main.js", 'r');
 console.log(file.read());
 file.close();
 file = fs.open("main.js", 'a');
 file.write("123");
 file.close();
 setTimeout(function () {
     phantom.exit(0)
 }, 2000);

對打開的文件渣锦,我們可以進行讀寫操作(具體使用與打開模式有關(guān))硝岗。如果對一個文件執(zhí)行了open,請別忘了在文件使用完成后袋毙,再對其執(zhí)行close型檀。

fs.read(path, mode/opts) String

fs.read() 方法對文件讀取做了封裝,不必關(guān)心文件的打開關(guān)閉听盖,返回值為文件內(nèi)容胀溺。

fs.write(path, content, mode/opts)

fs.write() 方法對文件寫入做了封裝,不必關(guān)心文件的打開關(guān)閉皆看。

其他API:

fs.size(path) Number:獲取文件大小

fs.copy(source, destination) :復(fù)制文件

fs.copyTree(source, destination) :復(fù)制目錄樹

fs.move(source, destination) :移動文件

fs.moveTree(source, destination) :移動目錄樹

fs.remove(file) :刪除文件

fs.removeTree(path) :刪除目錄

fs.join(partialPath[]) String:組合路徑

fs.split(path) String[]:切割路徑

fs.exist(path) Boolean:文件或目錄是否存在

fs.isFile(path) Boolean:指定路徑是否是文件

fs.isDirectory(path) Boolean:指定路徑是否是目錄

fs.list(path) String[]:獲取指定目錄下的文件/目錄名稱列表


System模塊

在文檔一開始就已經(jīng)提到過system模塊仓坞,一開始的例子中,我們使用了system模塊提供的 args 屬性⊙鳎現(xiàn)在重新來認識一下system模塊无埃。system模塊主要管理著一些與運行環(huán)境有關(guān)的屬性。

system.args String[]

獲取運行phantomjs時傳入的所有參數(shù)毛雇,這個不再贅述嫉称。

system.env Object

獲取當前的環(huán)境信息。包含操作系統(tǒng)信息灵疮、環(huán)境變量信息等等织阅。通過下面的代碼來查看一下吧:

var system = require('system');
 var env = system.env;
 Object.keys(env).forEach(function (key) {
	 console.log(key + '=' + env[key]);
 });
 setTimeout(function () {
	 phantom.exit(0)
 }, 2000);

system.os Object

獲取操作系統(tǒng)信息,返回一個簡單對象始藕,這個對象有3個屬性: architecture :架構(gòu)蒲稳,如“32bit”; name :操作系統(tǒng)名稱伍派; version :操作系統(tǒng)版本江耀。

system.pid Number

獲取當前進程的pid。

system.platform String

永遠返回 'phantomjs'


Web Server模塊

phantomjs支持一個簡單的web server模塊诉植, require('webserver') 即可引入祥国。web server模塊基于 mongoose 。不過最好不要在生產(chǎn)環(huán)境使用這樣的服務(wù)器模塊,因為現(xiàn)階段此模塊僅允許10個并發(fā)請求舌稀。

看一個簡單的例子吧:

var webserver = require('webserver');
var server = webserver.create();
var service = server.listen(8080, function(request, response) {
  response.statusCode = 200;
  response.write('<html><body>Hello!</body></html>');
  response.close();
});

首先需要創(chuàng)建服務(wù)器實例啊犬,然后調(diào)用 listen() 方法監(jiān)聽, listen() 方法的第一個參數(shù)可以為一個端口號壁查,也可以中 ip:port 這樣的ip+port組合方式觉至。第二個參數(shù)是處理請求的回調(diào)方法。下面描述一下 requestresponse 兩個對象睡腿。

request:

method :http請求的方法语御,get、post等

url : 包含http請求URL和get請求的query string(如果有的話)

httpVersion :當前采用的http協(xié)議的版本

headers :所有http請求頭部信息席怪,以鍵值對的形式提供

post :請求主體应闯,僅對post和put方法的請求有效

postRaw :如果Content-type為 'application/x-www-form-urlencoded' (表單上傳的默認值)時,post的原始信息會暫存在此屬性中挂捻。

response:

headers :以鍵值對的形式保存所有的HTTP請求頭部的信息碉纺,在第一次調(diào)用 write() 方法前一定要設(shè)置

setHeader(name, value) :設(shè)置或添加特定的頭部信息

header(name) :獲取特定的頭部信息

statusCode :設(shè)置HTTP狀態(tài)碼

setEncoding(encoding) : 標明傳給 write() 的數(shù)據(jù)需要轉(zhuǎn)換成什么格式,默認為UTF-8刻撒。如果數(shù)據(jù)為二進制字符串骨田,則設(shè)置為“binary”

write(data) :向response中發(fā)送數(shù)據(jù)塊,可以多次調(diào)用

writeHead(statusCode, headers) :向response中發(fā)送響應(yīng)頭部疫赎。 statusCode 是一個3位數(shù)字盛撑,表示HTTP狀態(tài)碼(如404)。后一個參數(shù)代碼響應(yīng)頭部

close() :關(guān)閉HTTP連接

為了避免客戶端檢測到連接中斷捧搞,記得最后再用

write()

方法發(fā)送一個空字符串(如:

response.write("")

)。

closeGracefully() :功能與 close() 一樣狮荔,不過更安全可靠胎撇,它能保證響應(yīng)頭部先發(fā)送,并自動在響應(yīng)最后加上 response.write("")

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末殖氏,一起剝皮案震驚了整個濱河市晚树,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌雅采,老刑警劉巖爵憎,帶你破解...
    沈念sama閱讀 216,470評論 6 501
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異婚瓜,居然都是意外死亡宝鼓,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,393評論 3 392
  • 文/潘曉璐 我一進店門巴刻,熙熙樓的掌柜王于貴愁眉苦臉地迎上來愚铡,“玉大人,你說我怎么就攤上這事×ち龋” “怎么了碍舍?”我有些...
    開封第一講書人閱讀 162,577評論 0 353
  • 文/不壞的土叔 我叫張陵,是天一觀的道長邑雅。 經(jīng)常有香客問我片橡,道長,這世上最難降的妖魔是什么淮野? 我笑而不...
    開封第一講書人閱讀 58,176評論 1 292
  • 正文 為了忘掉前任锻全,我火速辦了婚禮,結(jié)果婚禮上录煤,老公的妹妹穿的比我還像新娘鳄厌。我一直安慰自己,他們只是感情好妈踊,可當我...
    茶點故事閱讀 67,189評論 6 388
  • 文/花漫 我一把揭開白布猜扮。 她就那樣靜靜地躺著躏惋,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上柴淘,一...
    開封第一講書人閱讀 51,155評論 1 299
  • 那天,我揣著相機與錄音垮耳,去河邊找鬼废酷。 笑死,一個胖子當著我的面吹牛慎式,可吹牛的內(nèi)容都是我干的伶氢。 我是一名探鬼主播,決...
    沈念sama閱讀 40,041評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼瘪吏,長吁一口氣:“原來是場噩夢啊……” “哼癣防!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起掌眠,我...
    開封第一講書人閱讀 38,903評論 0 274
  • 序言:老撾萬榮一對情侶失蹤蕾盯,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后蓝丙,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體级遭,經(jīng)...
    沈念sama閱讀 45,319評論 1 310
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,539評論 2 332
  • 正文 我和宋清朗相戀三年渺尘,在試婚紗的時候發(fā)現(xiàn)自己被綠了挫鸽。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 39,703評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡沧烈,死狀恐怖掠兄,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤蚂夕,帶...
    沈念sama閱讀 35,417評論 5 343
  • 正文 年R本政府宣布迅诬,位于F島的核電站,受9級特大地震影響婿牍,放射性物質(zhì)發(fā)生泄漏侈贷。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 41,013評論 3 325
  • 文/蒙蒙 一等脂、第九天 我趴在偏房一處隱蔽的房頂上張望俏蛮。 院中可真熱鬧,春花似錦上遥、人聲如沸搏屑。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,664評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽辣恋。三九已至,卻和暖如春模软,著一層夾襖步出監(jiān)牢的瞬間伟骨,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 32,818評論 1 269
  • 我被黑心中介騙來泰國打工燃异, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留携狭,地道東北人。 一個月前我還...
    沈念sama閱讀 47,711評論 2 368
  • 正文 我出身青樓回俐,卻偏偏與公主長得像逛腿,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子鲫剿,可洞房花燭夜當晚...
    茶點故事閱讀 44,601評論 2 353

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

  • Spring Cloud為開發(fā)人員提供了快速構(gòu)建分布式系統(tǒng)中一些常見模式的工具(例如配置管理鳄逾,服務(wù)發(fā)現(xiàn),斷路器灵莲,智...
    卡卡羅2017閱讀 134,651評論 18 139
  • 前言 大家有沒有發(fā)現(xiàn)之前我們寫的爬蟲都有一個共性,就是只能爬取單純的html代碼殴俱,如果頁面是JS渲染的該怎么辦呢政冻?...
    追不到的那縷風閱讀 2,998評論 1 5
  • 你可能會把 NodeJS 用作網(wǎng)絡(luò)服務(wù)器,但你知道它還可以用來做爬蟲嗎线欲? 本教程中會介紹如何爬取靜態(tài)網(wǎng)頁——還有那...
    張嘉夫閱讀 5,091評論 3 51
  • 一明场、phantomjs介紹(1)一個基于webkit內(nèi)核的無界面瀏覽器,即沒有UI界面李丰,即它就是一個瀏覽器苦锨,只是其...
    王小魚鱻閱讀 2,854評論 0 0
  • https://nodejs.org/api/documentation.html 工具模塊 Assert 測試 ...
    KeKeMars閱讀 6,327評論 0 6