Selenium獲取PhantomJS輸出

0 背景

最近在做對網(wǎng)站的自動化測試帖池,最開始使用 Python Requests 進行測試奈惑,測試通過,然而頁面還是會出現(xiàn)這樣那樣問題睡汹。一方面是因為測試用例還不夠詳細肴甸,另一方面,Requests 是 url 層面或者說 api 層面的測試囚巴,并沒有完全模擬用戶在瀏覽器中的操作原在。比如,頁面有些元素是 JS 動態(tài)生成的彤叉,Requests 是無法得到的庶柿;或者頁面中的 img 或者 script 鏈接壞了,用 Requests 的話就需要去解析 html 了姆坚,這樣如果網(wǎng)站對排版做一點點改動就要重寫測試用例澳泵,非常費時費力。
經(jīng)過一番搜索兼呵,了解到兩個神器 Selenium 和 PhantomJS兔辅。關(guān)于這兩個軟件,就簡單說一下击喂,Selenium 是一個Web瀏覽器自動化測試框架维苔,而 PhantomJS 是一個基于 Webkit 的無 UI 的瀏覽器,詳細介紹請自行搜索懂昂。

1 目的

測試頁面中哪些鏈接是壞的介时。

2 遇到的問題

Selenium 可以通過 PhantomJS 獲取實際顯示的頁面(JS 動態(tài)生成的元素也可以得到),并且可以模擬用戶對頁面操作凌彬,但是上面提到的頁面中的鏈接壞了或者頁面的跳轉(zhuǎn)沸柔,它也是無法感知的,這些動作其實在 PhantomJS 中都可以得到铲敛,但是如果沒有做處理褐澎,在 Selenium 中是無法直接得到的。

3 解決

在 PhantomJS 中伐蒋,可以通過許多的句柄來獲取頁面的動作工三。比如下面這個腳本可以記錄整個頁面訪問的過程(netlog.js):

"use strict";
var page = require('webpage').create(),
    system = require('system'),
    address;

if (system.args.length === 1) {
  console.log('Usage: netlog.js <some URL>');
  phantom.exit(1);
} else {
  address = system.args[1];

  page.onResourceRequested = function (req) {
    console.log('requested: ' + JSON.stringify(req, undefined, 4));
  };

  page.onResourceReceived = function (res) {
    console.log('received: ' + JSON.stringify(res, undefined, 4));
  };

  page.open(address, function (status) {
    if (status !== 'success') {
      console.log('FAIL to load the address');
    }
    phantom.exit();
  });
}

執(zhí)行phantomjs netlog.js http://www.baidu.com迁酸,可以得到如下類似的輸出:

requested: {
    "headers": [
        {
            "name": "Accept",
            "value": "text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8"
        },
        {
            "name": "User-Agent",
            "value": "Mozilla/5.0 (Unknown; Linux x86_64) AppleWebKit/538.1 (KHTML, like Gecko) PhantomJS/2.1.1 Safari/538.1"
        }
    ],
    "id": 1,
    "method": "GET",
    "time": "2017-01-05T03:42:14.125Z",
    "url": "http://www.baidu.com/"
}
received: {
    "body": "",
    "bodySize": 215,
    "contentType": "text/html",
    "headers": [
        {
            "name": "Date",
            "value": "Thu, 05 Jan 2017 03:42:14 GMT"
        },
        {
            "name": "Content-Type",
            "value": "text/html"
        },
        {
            "name": "Content-Length",
            "value": "215"
        },

...

Selenium 正常調(diào)用 PhantomJS 的方法如下(Python 語言,下同):

from selenium import webdriver
driver = webdriver.PhantomJS()
driver.get('http://www.baidu.com')
print(driver.get_log('browser'))

其中最后一條語句可以得到頁面的 console.log 的輸出俭正,同時會生成一個 ghostdriver.log 的文件奸鬓,其中是 PhantomJS 的日志。
接下來就是如何在 Selenium 中獲取 PhantomJS 的輸出了掸读。

首先是在 Selenium 中讓 PhantomJS 執(zhí)行它的 API 的 Hack(參考):

driver = webdriver.PhantomJS()
script = "this.onResourceError = function(res) {console.log(JSON.stringify({'url': res.url, 'status': res.status}));};"
driver.command_executor._commands['executePhantomScript'] = ('POST', '/session/$sessionId/phantom/execute')
driver.execute('executePhantomScript', {'script': script, 'args': []})

但是這樣通過driver.get_log('browser')是得不到想要的內(nèi)容的串远,因為雖然和頁面 JS 的 console.log 是同樣的名字,然而 PhantomJS API 的 console.log 的輸出是在剛才提到的 ghostdriver.log 文件中儿惫,當然你也可以每次就讀取該文件來獲取內(nèi)容(可以通過 webdriver 的 service_log_path 參數(shù)來設(shè)置文件名)抑淫。筆者覺得這樣不夠優(yōu)雅,于是繼續(xù)……
通過閱讀 PhantomJS 的源碼姥闪,終于在 session.js 找到了一個隱藏的變量 browserLog 來實現(xiàn)這個功能始苇,這個變量其實就是driver.get_log('browser')讀取的變量,把你想要的內(nèi)容藏在這個變量里就好了筐喳。

from selenium import webdriver
driver = webdriver.PhantomJS()
script = "var page = this; page.onResourceError = function(res) {page.browserLog.push({'url': res.url, 'status': res.status});};"
driver.command_executor._commands['executePhantomScript'] = ('POST', '/session/$sessionId/phantom/execute')
driver.execute('executePhantomScript', {'script': script, 'args': []})
driver.get('http://www.baidu.com')
print(driver.get_log('browser'))

需要注意的是催式,1) PhantomJS 腳本中必須執(zhí)行語句var page = this,然后通過 page 變量來調(diào)用 API避归,否則會失敗荣月。

  1. driver.get_log('browser')同樣也會得到頁面的 console.log 的輸出,需要進行過濾梳毙。它的輸出格式是{"level": level, "message": message, "timestamp": timestamp}哺窄,可以通過filter(lambda x: 'url' in x, driver.get_log('browser'))語句過濾掉。
  2. 這個方法僅限于 PhantomJS账锹,其他的 WebDriver 還沒有測試過萌业。

Mission accomplished.

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市奸柬,隨后出現(xiàn)的幾起案子生年,更是在濱河造成了極大的恐慌,老刑警劉巖廓奕,帶你破解...
    沈念sama閱讀 211,639評論 6 492
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件抱婉,死亡現(xiàn)場離奇詭異,居然都是意外死亡桌粉,警方通過查閱死者的電腦和手機蒸绩,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,277評論 3 385
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來铃肯,“玉大人患亿,你說我怎么就攤上這事≡笛Γ” “怎么了窍育?”我有些...
    開封第一講書人閱讀 157,221評論 0 348
  • 文/不壞的土叔 我叫張陵,是天一觀的道長宴胧。 經(jīng)常有香客問我漱抓,道長,這世上最難降的妖魔是什么恕齐? 我笑而不...
    開封第一講書人閱讀 56,474評論 1 283
  • 正文 為了忘掉前任乞娄,我火速辦了婚禮,結(jié)果婚禮上显歧,老公的妹妹穿的比我還像新娘仪或。我一直安慰自己,他們只是感情好士骤,可當我...
    茶點故事閱讀 65,570評論 6 386
  • 文/花漫 我一把揭開白布范删。 她就那樣靜靜地躺著,像睡著了一般拷肌。 火紅的嫁衣襯著肌膚如雪到旦。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 49,816評論 1 290
  • 那天巨缘,我揣著相機與錄音添忘,去河邊找鬼。 笑死若锁,一個胖子當著我的面吹牛搁骑,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播又固,決...
    沈念sama閱讀 38,957評論 3 408
  • 文/蒼蘭香墨 我猛地睜開眼仲器,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了仰冠?” 一聲冷哼從身側(cè)響起娄周,我...
    開封第一講書人閱讀 37,718評論 0 266
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎沪停,沒想到半個月后煤辨,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 44,176評論 1 303
  • 正文 獨居荒郊野嶺守林人離奇死亡木张,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 36,511評論 2 327
  • 正文 我和宋清朗相戀三年众辨,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片舷礼。...
    茶點故事閱讀 38,646評論 1 340
  • 序言:一個原本活蹦亂跳的男人離奇死亡鹃彻,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出妻献,到底是詐尸還是另有隱情蛛株,我是刑警寧澤团赁,帶...
    沈念sama閱讀 34,322評論 4 330
  • 正文 年R本政府宣布,位于F島的核電站谨履,受9級特大地震影響欢摄,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜笋粟,卻給世界環(huán)境...
    茶點故事閱讀 39,934評論 3 313
  • 文/蒙蒙 一怀挠、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧害捕,春花似錦绿淋、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,755評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至盾沫,卻和暖如春冯吓,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背疮跑。 一陣腳步聲響...
    開封第一講書人閱讀 31,987評論 1 266
  • 我被黑心中介騙來泰國打工组贺, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人祖娘。 一個月前我還...
    沈念sama閱讀 46,358評論 2 360
  • 正文 我出身青樓失尖,卻偏偏與公主長得像,于是被迫代替她去往敵國和親渐苏。 傳聞我的和親對象是個殘疾皇子掀潮,可洞房花燭夜當晚...
    茶點故事閱讀 43,514評論 2 348

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