PhantomJS - 快速指南

PhantomJS - 概述

PhantomJS 被称为 无头浏览器,因为在执行 JavaScript 代码时无需浏览器参与。执行不会在浏览器显示中看到,而是在命令行提示符中看到。CSS 处理、DOM 操作、JSON、Ajax、Canvas、SVG 等功能都将在命令提示符中处理。PhantomJS 没有 GUI,因此,它的所有执行都在命令行中进行。

使用 PhantomJS,我们可以写入文件、读取文件内容或上传文件、进行屏幕截图、将网页转换为 pdf 等等。使用无头浏览器,您可以获得所有浏览器行为,即Cookies、Http 请求方法,即GET /POST、清除 Cookies、删除 Cookies等,重新加载页面,导航到其他页面

PhantomJS 使用 WebKit,它具有与著名浏览器(Google Chrome、Mozilla Firefox、Safari 等)类似的浏览环境。它还提供了许多 JavaScript API,可帮助截取屏幕截图、上传文件、写入文件、读取文件、与网页交互等。

PhantomJS 不支持 Flash 或视频,因为它需要插件,并且很难在命令行上支持它们。

PhantomJS 的功能

现在让我们了解 PhantomJS 提供的功能。

页面自动化

PhantomJS 允许您在其 API 的帮助下读取页面内容。它可以帮助操作 DOM,使用外部库执行所需的任务。

屏幕截图

PhantomJS 有助于对指定页面进行屏幕截图,并将其保存为 PNG、JPEG、PDF 和 GIF 等各种格式的图像。借助屏幕截图,它可以轻松帮助确保 Web 内容正常。

PhantomJS 提供属性和方法,借助这些属性和方法,开发人员可以调整屏幕截图的大小并指定他们想要捕获的区域。

无头测试

PhantomJS 帮助在命令行上测试 UI。同时,借助屏幕截图,它可以轻松帮助查找 UI 中的错误。PhantomJS 有时无法单独帮助测试。但是,它可以与其他测试库(如 Mocha、Yoeman 等)一起打包。您可以借助 PhantomJS 上传文件并提交表单。

PhantomJS 可用于测试跨站点的登录,并确保安全性不受损害。PhantomJS 可以与其他工具(如 CasperJS、Mocha、Qunit)一起使用,以使测试更加强大。

网络监控

PhantomJS 的重要功能之一是使用可用的 API 监控网络连接。PhantomJS 允许检查网络流量;它适合对网络行为和性能进行各种分析。

PhantomJS 可用于在实时环境中收集有关网页性能的数据。PhantomJS 可以与 Yslow 等工具一起使用,以收集任何网站的性能指标。

PhantomJS - 环境设置

PhantomJS 是一款免费软件,根据 BSD 许可证 分发。它易于安装,并提供多种功能来执行脚本。PhantomJS 可在 Windows、Linux 和 Mac 等多个平台上轻松运行。

要下载 PhantomJS,您可以访问 - http://phantomjs.org/,然后单击下载选项。

适用于 Windows

下载页面显示不同操作系统的下载选项。下载 zip 文件,解压后您将获得可执行文件 phantom.exe。将 PATH 环境变量设置为 phantom.exe 文件的路径。打开新的命令提示符并输入 phantomjs –v。它应该会为您提供正在运行的 PhantomJS 的当前版本。

对于 MAC OS X

下载适用于 MAC OS 的 PhantomJS zip 文件并提取内容。下载内容后,将 PhantomJS 移动到 - /usr/local/bin/。在终端执行 PhantomJS 命令,即 phantomjs –v,它应该会为您提供 PhantomJS 的版本描述。

Linux 64 位

下载适用于 Linux 64 位的 PhantomJS zip 文件并提取内容。下载内容后,将 PhantomJS 文件夹移动到 /usr/local/share/创建符号链接

sudo mv $PHANTOM_JS /usr/local/share
sudo ln -sf /usr/local/share/$PHANTOM_JS/bin/phantomjs /usr/local/bin。

在终端执行 phantomjs –v,它应该会给出 PhantomJS 的版本。

Linux 32 位

下载适用于 Linux 32 位的 PhantomJS zip 文件并提取内容。下载内容后,将 PhantomJS 文件夹移动到 /usr/local/share/ 并创建符号链接 −

sudo mv $PHANTOM_JS /usr/local/share
sudo ln -sf /usr/local/share/$PHANTOM_JS/bin/phantomjs /usr/local/bin。

在终端执行 phantomjs –v,它应该会给出 PhantomJS 的版本。

也可以通过单击以下链接从 git 存储库中获取 PhantomJS 源代码 - https://github.com/ariya/phantomjs/

要在 PhantomJS 中运行脚本,命令如下 −

phantomjs jsfile arg1 arg2… 

PhantomJS - Object

在本章中,我们将介绍 PhantomJS 的四个重要对象。它们如下所示 −

  • CookiesEnabled
  • Cookies
  • LibraryPath
  • Version

现在让我们详细讨论一下这些对象。

cookiesEnabled

它指示是否启用了 cookie。如果启用,它将返回 true;否则返回 false

语法

其语法如下 −

phantom.cookiesEnabled

示例

cookieenabled.js

phantom.addCookie ({  
   //使用 addcookie 属性添加 cookie
   name: 'c1', 
   value: '1', 
   domain: 'localhost' 
}); 

console.log("Cookie Enabled value is : "+phantom.cookiesEnabled); 
phantom.exit();

输出

命令 − phantomjs cookieenabled.js

Cookie Enabled value is : true 

Cookies

它有助于向域添加和设置 cookie。它返回一个对象,其中包含该域可用的所有 cookie。

语法

其语法如下 −

phantom.cookies;

示例

文件名:phantomcookie.js

phantom.addCookie ({ 
   name: 'c1', 
   value: '1', 
   domain: 'localhost' 
}); 
phantom.addCookie ({ 
   name: 'c2', 
   value: '2', 
   domain: 'localhost' 
}); 
phantom.addCookie ({ 
   name: 'c3', 
   value: '3', 
   domain: 'localhost' 
}); 
console.log(JSON.stringify(phantom.cookies)); 
phantom.exit();

输出

命令 − phantomjs phantomcookie.js

[{"domain":".localhost","httponly":false,"name":"c3","path":"/","secure":false, "
value":"3"},{"domain":".localhost","httponly":false,"name":"c2","path":"/","sec u
re":false,"value":"2"},{"domain":".localhost","httponly":false,"name":"c1","pat h
":"/","secure":false,"value":"1"}]

在上面的例子中,我们向 localhost 域添加了一些 cookie。然后我们使用 phantom.cookies 获取它。它使用 JSON stringify 方法将 JavaScript 对象转换为字符串,返回一个包含所有 cookie 的对象。您还可以使用 foreach 访问 cookie 的名称/值。

LibraryPath

PhantomJS libraryPath 存储 injectJS 方法要使用的脚本路径。

语法

其语法如下 −

phantom.libraryPath

示例

以下是查找版本的示例。

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

page.open('http://www.tutorialspoint.com/jquery', function(status) {
   if (status === "success") { 
      page.includeJs('http://ajax.googleapis.com/ajax/libs/jquery/1.7.2/jquery.min.js ', function() { 
         if (page.injectJs('do.js')) { 
            // returnTitle 是从我们的 do.js 文件加载的一个函数 - 见下文
            return returnTitle(); 
         });
         
         console.log(title); 
         phantom.exit(); 
      } 
   } 
});

window.returnTitle = function() { 
   return document.title;
}; 

上述程序生成以下输出

Jquery Tutorial

Version

它给出正在运行的 PhantomJS 的版本,并在对象中返回详细信息。例如:{"major":2,"minor":1,"patch":1

语法

其语法如下 −

phantom.version

示例

以下是查找版本的示例。

var a = phantom.version;
console.log(JSON.stringify(a));
console.log(a.major);
console.log(a.minor);
console.log(a.patch);
phantom.exit();

上述程序生成以下输出

{"major":2,"minor":1,"patch":1} 
2 
1 
1

在上面的例子中,我们使用了 console.log 来打印版本。目前,我们正在运行版本 2。它返回包含上述代码块中显示的详细信息的对象。

PhantomJS - 方法

PhantomJS 是一个无需浏览器即可执行 JavaScript 的平台。为此,使用以下方法,这些方法有助于添加 Cookie、删除、清除、退出脚本、注入 JS 等。

我们将在本章中进一步讨论这些 PhantomJS 方法及其语法。类似的方法,即addcookie,injectjs存在于网页模块中,将在后续章节中讨论。

PhantomJS 公开了以下方法,可以帮助我们在没有浏览器的情况下执行 JavaScript −

  • addCookie
  • clearCookie
  • deleteCookie
  • Exit
  • InjectJS

现在让我们通过示例详细了解这些方法。

addCookie

addcookie 方法用于添加 cookie 并存储在数据中。它类似于浏览器存储它的方式。它接受一个参数,该参数是一个具有 cookie 所有属性的对象,其语法如下所示 −

语法

其语法如下 −

phantom.addCookie ({ 
   "name" : "cookie_name",  
   "value" : "cookie_value", 
   "domain" : "localhost" 
});

name、value、domain 是必须添加到 addcookie 函数的属性。如果 cookie 对象中缺少任何此属性,此方法将失败。

  • name − 指定 cookie 的名称。

  • value − 指定要使用的 cookie 的值。

  • domain − 将应用 cookie 的域。

示例

以下是 addcookie 方法的示例。

var page = require('webpage').create(),url = 'http://localhost/tasks/a.html'; 
page.open(url, function(status) { 
   if (status === 'success') {     
      phantom.addCookie({   //添加名称 cookie1,其值为 1
         name: 'cookie1', 
         value: '1', 
         domain: 'localhost' 
      }); 
      phantom.addCookie({   // 添加值为 2 的 cookie2
         name: 'cookie2', 
         value: '2', 
         domain: 'localhost' 
      }); 
      phantom.addCookie({   // 添加值为 3 的 cookie3
         name: 'cookie3', 
         value: '3', 
         domain: 'localhost' 
      }); 
      console.log('Added 3 cookies'); 
      console.log('Total cookies :'+phantom.cookies.length);  
      
      // 将输出添加到 url 的 cookie 总数。 
   } else { 
      console.error('Cannot open file'); 
      phantom.exit(1); 
   } 
}); 

示例

a.html

<html>
   <head>
      <title>Welcome to phantomjs test page</title>
   </head>
   
   <body>
      <h1>This is a test page</h1>
      <h1>This is a test page</h1>
      <h1>This is a test page</h1>
      <h1>This is a test page</h1>
      <h1>This is a test page</h1>
      <h1>This is a test page</h1>
      <h1>This is a test page</h1>
      <h1>This is a test page</h1>
      <h1>This is a test page</h1>
   </body>
</html>

上述程序生成以下输出

Added 3 cookies 
Total cookies :3

代码注释一目了然。

clearCookies

此方法允许删除所有 cookie。

语法

其语法如下 −

phantom.clearCookies();

此概念的工作原理类似于通过在浏览器菜单中选择来删除浏览器 cookie。

示例

以下是 clearCookies 方法的示例。

var page = require('webpage').create(),url = 'http://localhost/tasks/a.html'; 
page.open(url, function(status) { 
   if (status === 'success') {     
      phantom.addCookie({   //添加名称 cookie1,其值为 1
         name: 'cookie1', 
         value: '1', 
         domain: 'localhost' 
      }); 
      phantom.addCookie({   // 添加值为 2 的 cookie2
         name: 'cookie2', 
         value: '2', 
         domain: 'localhost' 
      }); 
      phantom.addCookie({   // 添加值为 3 的 cookie3
         name: 'cookie3', 
         value: '3', 
         domain: 'localhost' 
      }); 
      console.log('Added 3 cookies'); 
      console.log('Total cookies :'+phantom.cookies.length); 
      phantom.clearCookies(); 
      console.log(
         'After clearcookies method total cookies :' +phantom.cookies.length); 
      
      phantom.exit();     
   } else { 
      console.error('Cannot open file'); 
      phantom.exit(1); 
   } 
}); 

a.html

<html>
   <head>
      <title>Welcome to phantomjs test page</title>
   </head>
   
   <body>
      <h1>This is a test page</h1>
      <h1>This is a test page</h1>
      <h1>This is a test page</h1>
      <h1>This is a test page</h1>
      <h1>This is a test page</h1>
      <h1>This is a test page</h1>
      <h1>This is a test page</h1>
      <h1>This is a test page</h1>
      <h1>This is a test page</h1>
   </body>
</html>

上述程序生成以下输出

Added 3 cookies 
Total cookies :3 
After clearcookies method total cookies :0 

deleteCookie

删除 CookieJar 中任何具有与 cookieName 匹配的"name"属性的 cookie。如果成功删除,它将返回 true;否则返回 false

语法

其语法如下 −

phantom.deleteCookie(cookiename);

让我们借助示例了解 addcookie、clearcookiesdeletecookie

示例

以下是演示 deleteCookie 方法 − 用法的示例。

文件:cookie.js

var page = require('webpage').create(),url = 'http://localhost/tasks/a.html'; 
page.open(url, function(status) { 
   if (status === 'success') {     
      phantom.addCookie({   //添加名称 cookie1,其值为 1
         name: 'cookie1', 
         value: '1', 
         domain: 'localhost' 
      }); 
      phantom.addCookie({   // 添加值为 2 的 cookie2
         name: 'cookie2', 
         value: '2', 
         domain: 'localhost' 
      });
      phantom.addCookie({   // 添加值为 3 的 cookie3
         name: 'cookie3', 
         value: '3', 
         domain: 'localhost' 
      });  
      console.log('Added 3 cookies'); 
      console.log('Total cookies :'+phantom.cookies.length); 
      
      //将输出添加到 url 的 cookie 总数。   
      console.log("Deleting cookie2"); 
      phantom.deleteCookie('cookie2'); 
      
      console.log('Total cookies :'+phantom.cookies.length); 
      phantom.clearCookies();
      
      console.log(
         'After clearcookies method total cookies :' +phantom.cookies.length); 
      phantom.exit(); 
   } else { 
      console.error('Cannot open file'); 
      phantom.exit(1); 
   } 
});

上述程序生成以下输出

phantomjs cookie.js
Added 3 cookies
Total cookies :3
Deleting cookie2
Total cookies :2
After clearcookies method total cookies :0

Exit

phantom.exit 方法将退出它已启动的脚本。它退出程序并返回值。如果没有传递任何值,则返回 '0'

语法

其语法如下 −

phantom.exit(value);

如果您未添加 phantom.exit,则命令行会假定执行仍在进行中且不会完成。

示例

让我们看一个例子来了解 exit 方法的用法。

console.log('Welcome to phantomJs'); // 输出 Welcome to phantomJS
var a = 1; 
if (a === 1) { 
   console.log('Exit 1'); //outputs Exit 1 
   phantom.exit(); // Code exits. 
} else { 
   console.log('Exit 2'); 
   phantom.exit(1); 
}

上述程序生成以下输出

phantomjs exit.js

Welcome to phantomJs 
Exit 1 

phantom.exit 之后的任何代码都不会执行,因为 phantom.exit 是结束脚本的方法。

injectJs

InjectJs 用于在 phantom 中添加 addtionaljs 文件。如果在当前 目录 librarypath 中找不到该文件,则 phantom 属性 (phantom.libraryPath) 将用作跟踪路径的附加位置。如果文件添加成功,则返回 true,否则,如果无法找到该文件,则返回 false 以防失败。

语法

其语法如下 −

phantom.injectJs(filename);

示例

让我们看下面的例子来了解injectJs的用法。

文件名:inject.js

console.log("Added file");

文件名:addfile.js

var addfile = injectionJs(inject.js);
console.log(addfile);
phantom.exit();

输出

命令 − C:\phantomjs\bin>phantomjs addfile.js

Added file // coming from inject.js
true

在上面的例子中,addfile.js 使用injectJs调用文件inject.js。执行addfile.js时,inject.js中的console.log将显示在输出中。由于文件inject.js已成功添加,因此addfile变量也显示为true。

PhantomJS - Webpage 网页模块属性

PhantomJS 提供了相当多的属性和方法来帮助我们与网页内的内容进行交互。

require("webpage").create() 命令创建一个网页对象。我们将使用此对象在下面列出的属性和方法的帮助下操作网页。

var wpage = require("webpage").create();

下表列出了我们将要讨论的所有网页属性。

S.No 属性和描述
1 canGoBack

如果导航历史记录中有上一页,则此属性返回 true;如果没有,则返回 false

2 canGoForward

如果导航历史记录中有下一页,则此属性返回 true;如果不是,则为 false

3 clipRect

clipRect 是一个具有 top、left、width 和 height 值的对象,用于在 render() 方法使用时捕获网页的图像。

4 Content

此属性包含网页的内容。

5 cookies

使用 cookies,您可以设置/获取 URL 上可用的 cookie。它还将为您提供 URL 上可用的 cookie 以及页面上设置的新 cookie。

6 customHeaders

customHeaders 指定将针对页面发出的每个请求发送到服务器的其他 HTTP 请求标头。

7 Event

它提供了事件的长列表,即修饰符、键详细信息。

8 focusedFrameName

返回当前聚焦框架的名称。

9 frameContent

此属性提供活动框架的内容。

10 frameName

返回当前聚焦框架的名称。

11 framePlainText

此属性还提供当前活动框架的内容,但仅提供没有任何 html 标签的内容。

12 frameTitle

提供活动框架的标题。

13 frameUrl

此属性将提供当前焦点框架的 url。

14 framesCount

提供页面上存在的框架数量。

15 framesName

提供框架名称数组。

16 libraryPath

此属性具有路径,由page.inectJs 方法。

17 navigationLocked

此属性定义是否允许页面导航。如果为 true,它将位于当前页面 URL 上,并且不允许单击页面转到下一页。

18 offlineStoragePath

此属性提供使用 window.localStorage 存储数据的路径。可以使用命令行中的 --local-storage-path 更改路径。

19 offlineStorageQuota

此属性定义您可以在 window.localStorage 中存储的最大数据量。该值为 5242880 字节,即 5MB。此值可以在命令行中使用以下命令覆盖 --localstorage-quota = size。

20 ownsPages

如果网页打开的页面是网页的子页面,ownsPages 将返回 true 或 false。

21 pagesWindowName

PagesWindowName 将提供使用 window.open 打开的窗口的名称

22 pages

pages 属性将为您提供使用 window.open 在页面中打开的页面数组。如果页面在 URL 中关闭,则不会考虑您引用的页面。

23 paperSize

此属性提供大小,即需要将网页转换为 pdf 格式时网页的尺寸。paperSize 包含对象中所需的尺寸。

24 plaintext

此属性还提供当前活动框架的内容,但仅提供没有任何 html 标签的内容。

25 scrollPosition

这包含指示滚动位置的对象。它提供左侧和顶部。

26 settings

当使用 page.open 方法时,此属性将提供网页的设置。一旦页面加载,设置属性中的更改将不会产生任何影响。

27 title

此属性将为您提供您正在阅读的页面的标题。

28 url

此属性将提供页面 url。

29 viewportSize

此属性允许更改窗口显示的大小。它包含宽度和高度,您可以根据需要读取或更改它们。

30 windowName

提供窗口的名称。

31 zoomFactor

此属性指定 render 和 renderBase64 方法的缩放因子。它有助于缩放页面并在需要时进行屏幕截图。

PhantomJS - Webpage 网页模块方法

Webpage 网页模块具有用于Cookie、框架、页面导航、重新加载、渲染文件上传的方法。

以下是网页上可用的方法。

S.No 方法和描述
1 addCookie()

addCookie 方法将 cookie 添加到指定页面。

2 childFramesCount()

根据 http://phantomjs.org,此方法已弃用。

3 childFramesName()

根据 http://phantomjs.org。

4 clearCookies()

将删除指定页面的所有 cookie。

5 close()

此方法用于关闭页面并释放使用的内存。一旦调用 close,任何网页方法或属性都将不起作用。

6 currentFrameName()

根据 http://phantomjs.org,此方法已弃用。

7 deleteCookie()

这将删除名称与给定页面网址的现有 cookie 列表匹配的 cookie。

8 evaluateAsync()

在页面内异步评估给定函数,而不阻止当前执行。此函数有助于异步执行某些脚本。

9 evaluateJavascript()

EvaluateJavaScript 有助于以字符串形式执行传递给它的函数。请注意,传递的字符串必须只是一个函数。

10 evaluate()

Evaluate 将执行传递给它的函数。如果函数包含控制台消息,则不会直接显示在终端中。要显示任何控制台消息,您需要使用 onConsoleMessage 幻像回调。

11 getPage()

这将为您提供与 getpage 中传递的窗口名称匹配的子页面。

12 goBack()

如果导航未锁定,它会提供导航历史记录中的上一页。

13 goForward()

如果导航未锁定,它会在导航历史记录中显示下一页。

14 go()

此方法允许您浏览页面。

15 includeJs()

Includejs 在页面上执行外部 JS 文件,并在完成后执行回调函数。

16 injectJs()

InjectJs 将指定文件中的外部脚本包含到页面中。如果当前目录中没有该文件,则使用 libraryPath 对文件进行额外搜索。如果文件已注入,则返回 true,否则返回 false。

17 openUrl()

OpenUrl 打开一个网页,和 PhantomJS 的 open 方法类似,OpenUrl 还有一些额外的参数,包括 httpConf、设置和回调函数。

18 open()

Open 用于打开一个网页。

19 release()

Release 会释放页面的内存堆使用量,调用 release 后不要再使用页面实例方法。此方法和 close 方法类似,已弃用。而是使用 wpage.close()。

20 reload()

Reload 用于重新加载当前使用的页面。

21 renderBase64()

此方法获取屏幕截图并以 base46 格式将图像作为字符串提供。Renderbase64 支持 PNG、JPEG 和 JPG 等格式。目前不支持 gif。您可以使用 clipRect 属性来定义图像捕获的部分。

22 renderBuffer()

RenderBuffer 将网页捕获到图像缓冲区,可直接发送到服务器。支持的格式包括 PNG、GIF 和 JPEG。

23 render()

Render 有助于获取图像缓冲区并按照指定的格式保存。

24 sendEvent()

用于向网页发送事件。它们不是 dom 事件。这些事件中的每一个都是根据用户交互发送到网页的。

25 setContent()

setcontent 将使用指定的内容更改指定 url 的页面内容。

26 stop()

它有助于停止页面加载。

27 switchToChildFrame()

不建议使用switchToFrame();

28 switchToFocusedFrame()

选择焦点所在的帧。

29 switchToFrame()

选择具有指定名称且为当前帧的子帧的帧。

30 switchToMainFrame()

选择主框架,即根窗口。

31 switchToParentFrame()

它采用当前子框架的父框架。

32 uploadFile()

此方法用于处理使用 html 中的表单完成的文件上传。PhantomJS 没有直接使用表单执行此操作的方法,可以使用 uploadFile 方法实现相同的操作。它采用 html 标签选择器来选择文件位置和要复制到的目的地。

Webpage 网页模块事件/回调

下表描述了Webpage 网页模块可用的回调。

S.No 回调和说明
1 onAlert()

当页面上有警报时,将调用此回调;回调接受一个字符串,但不返回任何内容。

2 onCallback()

OnCallback 用于将值从网页传递到网页对象,它是使用 window.callPhantom() 方法完成的,该方法在内部调用 onCallback 函数。

3 onClosing()

当使用 page.close() 方法或 window.close() 方法关闭窗口时,将调用此方法。

4 onConfirm()

当页面上有使用 ok /cancel 调用的确认消息时,将调用此回调。

5 onConsoleMessage()

当网页中使用控制台消息时,将使用此回调。 onConsoleMessage 方法采用 3 个参数。

6 onError()

当出现 JavaScript 错误时,将调用此回调。 onError 的参数是 msg 和 stack trace,后者是一个数组。

7 onFilePicker()

这用于上传文件,当用户想要上传文件时会调用回调。

8 onInitialized()

在页面加载前调用此回调。

9 onLoadFinished()

当打开的页面完全加载时,会调用此函数。它有一个参数,用于指示加载是成功还是失败。

10 onLoadStarted()

页面开始加载时会调用此回调。

11 onNavigationRequested()

此回调指示导航事件何时发生。

12 onPageCreated()

此回调是当页面打开新的子窗口时调用。

13 onPrompt()

当网页调用提示时,会调用此回调。它需要 2 个参数,消息和答案。返回值是一个字符串。

14 onResourceError()

当网页无法上传文件时,会调用此回调。

15 onResourceReceived()

当收到页面请求的资源时,会调用此回调。

16 onResourceRequested()

此函数当页面请求资源时调用。

17 onResourceTimeout()

当使用 settings.resourceTimeout 时,请求的资源超时,会调用此回调。

18 onUrlChanged()

当使用导航更改当前 URL 时,会调用此回调。它有一个回调参数,即新的 URL targetUrl 字符串。

网页子进程模块

Phantomjs 子进程模块有助于与子进程交互,并使用 stdin /stdout/stderr 与它们通信。子进程可用于执行 打印、发送邮件 等任务,或 调用用其他语言编写的程序。要创建子进程模块,您需要引用。

例如 −

var process = require("child_process");

Spawn 方法

使用 spawn 子进程,您可以订阅其 stdoutstderr 流以实时获取数据。

语法

其语法如下 −

var spawn = require('child_process').spawn;

示例

让我们看一个 spawn 方法的示例。

var process = require("child_process")
var spawn = process.spawn
var child = spawn("cmd", ['/c', 'dir']);

child.stdout.on("data", function (data) {
   console.log("spawnSTDOUT---VALUE:", JSON.stringify(data))
})
child.stderr.on("data", function (data) {
   console.log("spawnSTDERR:", JSON.stringify(data))
})
child.on("exit", function (code) {
   console.log("spawnEXIT:", code)
})

Output

上述程序生成以下输出。

spawnSTDOUT---VALUE: " Volume in drive C is OS
"
spawnSTDOUT---VALUE: " Volume Serial Number is 7682-9C1B

 Directory of C:
\phantomjs\bin

"
spawnSTDOUT---VALUE: "20-05-2017  10:01
<DIR>          .
20-05-2017  10:01
<DIR>          ..
13-05-2017  20:48   12 a,txt.txt
07-05-2017  08:51
63 a.js
06-05-2017  16:32           120,232 a.pdf
13-05-2017  20:49 
spawnEXIT: 0 

PhantomJS - 文件系统模块属性

文件系统模块有许多 API 来处理文件和目录。您可以创建/写入和删除文件/目录。要开始使用文件系统模块,您必须引用 fs 模块

var fs = require('fs');

文件系统模块有两个可用属性:SeparatorWorking Directory。让我们详细了解它们。

分隔符

它告诉您用于文件路径的分隔符。

  • 对于 Windows:\
  • 对于 Linux:/

语法

其语法如下 −

fs.seperator

示例

var fs = require('fs');
console.log(fs.seperator);
phantom.exit();

上述程序生成以下输出

undefined

workingDirectory

工作目录是PhantomJS执行的目录。

语法

其语法如下 −

var fs = require('fs');
fs.workingDirectory;

示例

var fs = require('fs');
console.log(fs.workingDirectory);
phantom.exit();

上述程序生成以下输出

C:/phantomjs/bin

PhantomJS - 文件系统模块方法

下表包含文件系统模块上可用的所有方法及其说明。

S.No 方法和描述
1 absolute

此方法提供 PhantomJS 运行的绝对路径。

2 changeWorkingDirectory

这允许您更改工作目录并返回 true,如果成功,否则返回 false。

3 copyTree

copyTree 将目录从一个路径复制到另一个路径。第一个参数是源文件夹,第二个参数是目标文件夹。

4 copy

此方法有助于将文件从一个位置复制到另一个位置。它需要两个参数。第一个参数是源文件,第二个参数是要复制的文件路径。如果源文件或目标文件不存在,它将抛出错误。

5 exists

它检查系统中是否存在给定的文件路径。如果存在则返回 true,否则返回 false。

6 isAbsolute

如果文件路径是绝对路径,则此方法返回 true;如果是相对路径,则返回 false。

7 isDirectory

isDirectory 告知给定文件是否为目录。如果是目录,则返回 true,否则返回 false。如果给定路径不存在,则返回 false。

8 isExecutable

此方法将告知给定文件是否可执行。如果可执行,则返回 true,否则返回 false。

9 isFile

这详细说明了给定的文件路径是否为文件。如果是文件则返回 true,如果不是则返回 false。

10 isLink

如果文件路径是符号链接则返回 true,否则返回 false。

11 isReadable

检查给定的文件是否可读。如果是,则返回 true,否则返回 false。

12 isWritable

它判断给定文件是否可写。如果是,则返回 true,否则返回 false。

13 lastModified

提供对文件的最后修改的详细信息。它告诉文件最后修改的日期和时间。

14 list

它提供目录中存在的所有文件。

15 makeDirectory

创建一个新目录。

16 makeTree

makeTree 创建所有必要的文件夹以便能够形成最终目录。如果创建成功则返回 true,否则返回 false。如果目录已经存在,它将返回 true。

17 move

它将文件从一个路径移动到另一个路径。

18 open

它用于打开文件。

19 readLink

这将返回由符号链接(或Windows 上的快捷方式)。如果路径不是符号链接或快捷方式,它将返回一个空字符串。

20 read

这将读取给定的文件。

21 removeDirectory

这将删除给定的目录。

22 removeTree

它将从给定的文件夹中删除所有文件和文件夹,并且最后删除文件夹本身。如果在执行此过程时出现任何错误,它将抛出错误 - "无法删除目录树 PATH"并挂起执行。

23 remove

它删除给定的文件。

24 size

它给出文件的大小。

25 touch

它创建一个给定的文件。

26 write

写入给定文件。

PhantomJS - 系统模块属性

在本章中,我们将讨论 PhantomJS 的各种系统模块属性。

args

PhantomJS 的系统模块具有不同的属性,有助于传递参数、了解执行的文件等。

args 属性基本上返回在命令行传递的参数。您还可以传递要读取的页面 URL。如果您想要存储屏幕截图 pdf 文件或上传文件,可以将详细信息传递到命令行,并使用 args 属性读取。

让我们找到传递到命令行的每个参数的长度和获取方法。

语法

其语法如下 −

var system = require('system');
system.args;

示例

查看以下示例以了解此属性的工作原理。

var system = require('system');
console.log(system.args.length);

if (system.args.length>0) {
   console.log(JSON.stringify(system.args));
}
phantom.exit();

上述程序生成以下输出

Command − phantomsjs args.js http://localhost/tasks/request.html

2
["args.js","http://localhost/tasks/request.html"]

第一个值是文件的名称,下一个值是传递的 URL。您可以在命令行中传递更多参数,并使用 system.args 获取相同的参数。

env

env 属性返回系统的详细信息。

语法

其语法如下 −

var system = require('system');
system.env;

示例

var system = require('system');
console.log(JSON.stringify(system.env));
phantom.exit();

上述程序生成以下输出。

{"=::":"::\","=C:":"C:\phantomjs\bin","=ExitCode":"00000000","ALLUSERSPROFILE":
"C:\ProgramData","APPDATA":"C:\Users\UserName\AppData\Roaming","COMPUTERNAME":
"X","ComSpec":"C:\Windows\system32\cmd.exe","CommonProgramFiles":
"C:\Program Files (x86)\Common Files","CommonProgramFiles(x86)":
"C:\Program Files (x86)\Common Files","CommonProgramW6432":
"C:\Program Files\Common Files","FP_NO_HOST_CHECK":"NO","HOMEDRIVE":"C:",
"HOMEPATH":"\Users\UserName","LOCALAPPDATA":
"C:\Users\UserName\AppData\Local","LOGONSERVER":"\\MicrosoftAccount",
"NUMBER_OF_PROCESSORS":"2","OS":"Windows_NT","PATHEXT":".COM;.EXE;.BAT;.CMD;.VBS ;
.VBE;.JS;.JSE;.WSF;.WSH;.MSC","PROCESSOR_ARCHITECTURE":"x86","PROCESSOR_ARCHITEW64 32":
"AMD64","PROCESSOR_IDENTIFIER":"Intel64 Family 6 Model 58Stepping9,GenuineIntel",
"PROCESSOR_LEVEL":"6","PROCESSOR_REVISION":"3a09","PROMPT":
"$P$G","PSModulePath":"C:\Windows\system32\WindowsPowerShell\v1.0\
Modules\" ,"PUBLIC":"C:\Users\Public","Path":
"C:\Program Files\Dell\DW WLAN Card;
c:\Program Files (x86)\Intel\iCLS Client\;c:\Program Files\Intel\iCLSClient\;
C:\Windows\system32;C:\Windows;C:\Windows\System32\ \Wbem;
C:\Windows\System32\WindowsPowerShell\v1.0\;
C:\Program Files\Intel\Intel(R) Management Engine Components\DAL;
C:\Program Files\Intel\Intel(R) Management Engine Components\IPT;
C:\Program Files (x86)\Intel\Intel(R) Management Engine Components\DAL;
C:\Program Files (x86)\Intel\Intel(R) 
ManagementEngineComponents\IPT;c:\ProgramFiles\WIDCOMM\BluetoothSoftware\;
c:\ProgramFiles\WIDCOMM\BluetoothSoftware\syswow64;
C:\ProgramFiles(x86)\WindowsLive\Shared;C:\ProgramFiles\nodejs\;
C:\ProgramFiles\Git\cmd;C:\ProgramFiles\ OpenVPN\bin;
C:\ProgramFiles(x86)\Skype\Phone\;C:\Users\UserName\AppData\Roaming
\npm","ProgramData":
"C:\ProgramData","ProgramFiles":"C:\ProgramFiles(x86)", 
"ProgramFiles(x86)":"C:\ProgramFiles(x86)","ProgramW6432":
"C:\ProgramFiles","SESSIONNAME":"Console","SystemDrive":
"C:","SystemRoot":"C:\Windows","TEMP":"C:\Users\ \Username~1\AppData\Local\Temp",
"TMP":"C:\Users\Username~1\AppData\Local\Temp",
"USERDOMAIN":"USER","USERDOMAIN_ROAMINGPROFILE":"USER","USERNAME":"X Y","USERPROFILE":
"C:\Users\X Y","windir":"C:\Windows"}

OS

它返回所用操作系统的详细信息。它返回一个包含体系结构、操作系统名称和版本的对象。

语法

其语法如下 −

var system = require('system');
system.os;

示例

var system = require('system');
console.log(JSON.stringify(system.os));
phantom.exit();

上述程序生成以下输出。

{"architecture":"32bit","name":"windows","version":"8.1"}

pid

此属性返回进程 ID。

语法

其语法如下 −

var system = require('system');
system.pid;

示例

让我们看一个 pid 属性的示例。

var system = require('system');
console.log(system.pid);
phantom.exit();

上述程序生成以下输出。

2160

platform

此属性返回我们正在处理的平台。

语法

其语法如下 −

var system = require('system');
system.platform;

示例

var system = require('system');
console.log(system.platform);
phantom.exit();

上述程序生成以下输出。

Phantomjs

PhantomJS - Web 服务器模块属性

PhantomJS 使用名为 mongoose 的嵌入式 Web 服务器。目前,PhantomJS 无法与任何其他生产 Web 服务器连接。就连接而言,它一次可以处理 10 个连接,并且超过 10 个请求将在队列中等待。

要启动 Web 服务器,我们需要使用以下语法 −

var webserver = require ('webserver');

让我们了解 Port 属性,该属性用于侦听发送到 Web 服务器的请求。

port

Web 服务器的 Port 属性用于侦听发送给它的请求。

语法

其语法如下 −

var server = require('webserver').create();
var listening = server.listen(port, function (request, response) {});

示例

让我们举一个例子来了解 port 属性的工作原理。

var webserver = require('webserver'); 
var server = webserver.create(); 
var service = server.listen(8080,function(request,response){  
}); 
if(service) console.log("server started - http://localhost:" + server.port); 

上述程序生成以下输出。

server started - http://localhost:8080

PhantomJS - Web 服务器模块方法

在本章中,我们将讨论 PhantomJS 的 Web 服务器模块的各种方法。

close

close 方法用于关闭 Web 服务器。

语法

其语法如下 −

var server = require('webserver').create();
server.close();

示例

以下示例展示了如何使用 close 方法。

var webserver = require('webserver');
var server = webserver.create();
var service = server.listen(8080,function(request,response){
});

if(service) console.log("server started - http://localhost:" + server.port);
console.log(server.port);
server.close();
console.log(server.port);

上述程序生成以下输出

server started - http://localhost:8080 
8080

在这里,我们在关闭服务器后对 server.port 进行了控制。因此,由于 Web 服务器已关闭,因此它不会响应。

listen

server.listen 方法采用端口和回调函数以及两个参数,即 - Request ObjectResponse Object

Request Object 包含以下属性 −

  • Method − 这定义了方法 GET /POST。

  • URL − 这显示请求的 URL。

  • httpVersion − 这显示实际的 http 版本。

  • Headers −这将显示所有带有键值对的标头。

  • Post − 请求正文仅适用于 post 方法。

  • postRaw − 如果 Content-Type 标头设置为"application/x-www-formurlencoded",则帖子的原始内容将存储在此额外属性 (postRaw) 中,然后该帖子将自动使用 URL 解码版本的数据进行更新。

Response Object 包含以下属性 −

  • Headers − 包含所有 HTTP 标头作为键值对。应在首次调用 write 之前设置它。

  • SetHeader −这将设置一个特定的标头。

  • Header (name) − 它返回给定标头的值。

  • StatusCode − 它设置返回的 HTTP 状态代码。

  • SetEncoding (encoding) − 它用于转换给定给 write() 的数据。默认情况下,数据将转换为 UTF-8。如果数据是二进制字符串,则指示"二进制"。如果数据是缓冲区(例如来自 page.renderBuffer),则不需要。

  • Write (data) − 它发送响应主体的数据。可以多次调用。

  • WriteHead (statusCode, headers) − 它向请求发送响应标头。状态代码是 3 位 HTTP 状态代码(例如 404)。最后的参数和标头是响应标头。

  • Close − 它关闭 http 连接。

  • CloseGracefully − 它与 close() 类似,但它确保首先发送了响应标头。

语法

其语法如下 −

var server = require('webserver').create();
var listening = server.listen(8080, function (request, response) {}

示例

让我们举一个例子来了解 listen 方法的工作原理。

var page = require('webpage').create(); 
var server = require('webserver').create(); 
var port = 8080; 
var listening = server.listen(8080, function (request, response) { 
    console.log("GOT HTTP REQUEST");
    console.log(JSON.stringify(request, null, 4));
    
    // 我们在这里设置标头
    response.statusCode = 200;
    response.headers = {"Cache": "no-cache", "Content-Type": "text/html"};
    
    // 上面的标头现在将被隐式发送
    // 现在我们编写正文
    response.write("<html><head><title>Welcone to Phantomjs</title></head>");
    r​​esponse.write("<body><p>Hello World</p></body></html>");
    r​​esponse.close();
}); 

if (!listening) { 
   console.log("could not create web server listening on port " + port); 
   phantom.exit(); 
} 

var url = "http://localhost:" + port + "/foo/response.php"; 
console.log("sending request to :" +url); 
page.open(url, function (status) { 
   if (status !== 'success') { 
      console.log('page not opening'); 
   } else { 
      console.log("Getting response from the server:"); 
      console.log(page.content); 
   } 
   
   phantom.exit(); 
});

上述程序生成以下输出

sending request to :http://localhost:8080/foo/response.php 
GOT HTTP REQUEST { 
   "headers": {
      "Accept": "text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8", 
      "Accept-Encoding": "gzip, deflate", 
      "Accept-Language": "en-IN,*", 
      "Connection": "Keep-Alive", 
      "Host": "localhost:8080", 
      "User-Agent": "Mozilla/5.0 (Windows NT 6.2; WOW64) AppleWebKit/538.1 
         (KHTML, like Gecko) PhantomJS/2.1.1 Safari/538.1" 
   }, 
   "httpVersion": "1.1", 
   "method": "GET", 
   "url": "/foo/response.php" 
} 
Getting response from the server: 
<html><head><title>Welcone to Phantomjs</title></head><body><p>Hello World</p></body>
</html> 

PhantomJS - 命令行界面

可以使用关键字"phantomjs"和文件名称来执行 PhantomJS。例如,"phantomjs file.js"。

您还可以将参数传递给"file.js",如下所示 −

phantomjs [options] file.js arg1 arg2 ...

让我们来看看命令行中可用的一些选项。

S.No 选项 &描述
1

--help 或 –h

将显示所有命令行选项。立即停止并且不会运行传递的脚本。

2

--version 或 –v

打印正在运行的 PhantomJS 版本。这将停止要运行的脚本的执行。

3

--debug[true|false]

打印警告和调试消息。默认情况下,它设置为 false。您也可以使用 [yes|no]。

4

--cookies-file = /path/to/cookies.txt

用于存储持久性 cookie 的文件名。

5

--diskcache=[true|false]

启用磁盘缓存。它还接受值 [yes|no]

6

--disk-cahe-path

磁盘缓存的路径。

7

--ignore-sslerrors=[true|false]

忽略 SSL 错误。例如 - 过期或自签名证书错误。默认值为 false。它也接受值 [yes|no]。

8

--loadimages=[true|false]

加载所有内联图像。默认值为 true。它还需要 [yes|no]。

9

--local-storagepath=/some/path

保存 LocalStorage 内容和 WebSQL 内容的路径。

10

--local-storagequota=number

允许数据的最大大小。

11

--local-url-access

允许使用'file:///' URL(默认为 true)。

12

--local-to-remote-urlaccess=[true|false]

允许本地内容访问远程 URL。默认值为 false。它还可以使用值 [yes|no]。

13

--max-disk-cachesize=size

限制磁盘缓存的大小(以 KB 为单位)

14

--offline-storage-path

指定离线存储的位置。

15

--offline-storage-quota

设置离线存储的最大大小(以 KB 为单位)。

16

--outputencoding=encoding

设置用于终端输出的编码。默认为 utf-8。

17

--proxy=address:port

指定要使用的代理服务器(例如 – proxy=192.168.1.1:8080)

18

--proxytype=[http|socks5|none]

指定代理服务器的类型(默认为 http)

19

--proxy-auth

代理的身份验证信息。例如 –

--proxy-auth=username:password

20

--scriptencoding=encoding

设置脚本使用的编码。默认为 utf8。

21

--script-language

设置脚本语言。

PhantomJS - 屏幕截图

PhantomJS 在截取网页屏幕截图和将网页转换为 PDF 方面非常有用。我们在这里给出了一个简单的示例来演示它的工作原理。

示例

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

执行上述程序,输出将保存为 phantom.png

Optimal Solution

将网页转换为 PDF

PhantomJS 还有助于将网页转换为添加了页眉和页脚的 PDF。请查看以下示例以了解其工作原理。

var wpage = require('webpage').create(); 
var url = "https://en.wikipedia.org/wiki/Main_Page"; 
var output = "test.pdf"; 

wpage.paperSize = { 
   width: screen.width+'px', 
   height: '1500px', 
   
   margin: {
      'top':'50px', 
      'left':'50px', 
      'rigtht':'50px' 
   }, 
   orientation:'portrait', 
   header: { 
      height: "1cm", 
      contents: phantom.callback(function(pageNumber, nPages) { 
         return "<h5>Header <b>" + pageNumber + " / " + nPages + "</b></h5>"; 
      }) 
   }, 
   footer: { 
      height: "1cm", 
      contents: phantom.callback(function(pageNumber, nPages) {   
         return "<h5>Footer <b>" + pageNumber + " / " + nPages + "</b></h5>"; 
      }) 
   } 
} 
wpage.open(url, function (status) { 
   if (status !== 'success') { 
      console.log('Page is not opening'); 
      phantom.exit(); 
   } else { 
      wpage.render(output); 
      phantom.exit();     
   } 
});

上述程序生成以下输出

The above will convert the page into pdf and will be saved in test.pdf

将 Canvas 转换为图像

Phantomjs 可以轻松将 Canvas 转换为图像。查看以下示例以了解其工作原理。

var page = require('webpage').create(); 
page.content = '<html><body><canvas id="surface" width="400" height="400"></canvas></body></html>'; 

page.evaluate(function() {
   var context,e1; 
   el = document.getElementById('surface'); 
   
   context = el.getContext('2d'); 
   context.font = "30px Comic Sans MS"; 
   context.fillStyle = "red"; 
   context.textAlign = "center"; 
   context.fillText("Welcome to PhantomJS ", 200, 200); 
   
   document.body.style.backgroundColor = 'white'; 
   document.body.style.margin = '0px'; 
}); 
page.render('canvas.png'); 
phantom.exit(); 

上述程序生成以下输出

Welcome Phantomjs h1>PhantomJS - 页面自动化

PhantomJS 在其网页模块 API 的帮助下,可以操作网页并执行诸如 DOM 操作、单击按钮等操作。

从页面获取图像

以下程序展示了如何使用 PhantomJS 从页面获取图像。

var wpage = require('webpage').create();
wpage.onConsoleMessage = function(str) {
   console.log(str.length);
}
wpage.open("http://phantomjs.org", function(status) {
   console.log(status);
   var element = wpage.evaluate(function() {
      var imgdata =  document.querySelectorAll('img');
      var imgsrc = [];
      
      if (imgdata) {
         for (var i in imgdata) {
            imgsrc.push(imgdata[0].src);
         }
      }
      return imgsrc;
   });
   console.log(JSON.stringify(element));
});

上述程序生成以下输出

Success 
["http://phantomjs.org/img/phantomjslogo.png","http://phantomjs.org/img/phantom 
js-logo.png","http://phantomjs.org/img/phantomjslogo.png","http://phantomjs.org 
/img/phantomjs-logo.png"]

可以使用 injectJS 网页方法 在页面中包含外部 JavaScript。有许多属性和方法,可以帮助页面自动化并执行许多其他操作。您可以参考网页模块,其中详细解释了属性和方法。

PhantomJS - 网络监控

借助 PhantomJS,我们可以监控网络并验证特定网页的行为和性能。PhantomJS 中有回调,即 onResourceRequestedonResourceReceived,它们有助于监控给定页面的流量。

示例

以下示例展示了如何使用 PhantomJS 监控给定页面的流量。

function createHAR(address, title, startTime, resources) {  
   
   // 此函数格式化来自 onresourcerequest 和 onresourcereceived 的数据
   var entries = []; 
   
   resources.forEach(function (resource) { 
      var request = resource.request, startReply = resource.startReply, 
         endReply = resource.endReply;  
      
      if (!request || !startReply || !endReply) { 
         return; 
      }  
      
      // 从 HAR 文件中排除数据 URI,因为
      // 它们未包含在规范中
      if (request.url.match(/(^data:image\/.*)/i)) { 
         return; 
      }  
      entries.push ({ 
         startedDateTime: request.time.toISOString(), 
         time: endReply.time - request.time, 
         
         request: { 
            method: request.method, 
            url: request.url, 
            httpVersion: "HTTP/1.1", 
            cookies: [], headers: request.headers, 
            queryString: [], 
            headersSize: -1, 
            bodySize: -1 
         }, 
         response: { 
            status: endReply.status, 
            statusText: endReply.statusText, 
            httpVersion: "HTTP/1.1", 
            cookies: [], 
            headers: endReply.headers, 
            redirectURL: "", 
            headersSize: -1, 
            bodySize: startReply.bodySize, 
            
            content: { 
               size: startReply.bodySize, 
               mimeType: endReply.contentType 
            } 
         }, 
         cache: {}, 
         timings: { 
            blocked: 0, 
            dns: -1, 
            connect: -1, 
            send: 0, 
            wait: startReply.time - request.time, 
            receive: endReply.time - startReply.time, 
            ssl: -1 
         }, 
         pageref: address 
      }); 
   });  
   return { 
      log: { 
         version: '1.2', creator: { 
            name: "PhantomJS", 
            version: phantom.version.major + '.' + phantom.version.minor + 
               '.' + phantom.version.patch 
         }, 
         pages: [{ 
            startedDateTime: startTime.toISOString(), 
            id: address, 
            title: title, 
            
            pageTimings: { 
               onLoad: page.endTime - page.startTime 
            } 
         }], 
         entries: entries 
      } 
   }; 
}  
var page = require('webpage').create(), system = require('system'); 
var fs = require('fs');   

if (system.args.length === 1) { 
   console.log('Usage: netsniff.js <some URL>'); 
   phantom.exit(1); 
} else { 
   page.address = system.args[1]; 
   page.resources = []; 
   
   page.onLoadStarted = function () {  // 页面加载时调用
      page.startTime = new Date(); 
   };  
   page.onResourceRequested = function (req) {  
      // 当从给定的页面 URL 请求任何文件时调用
      page.resources[req.id] = { 
         request: req, 
         startReply: null, 
         endReply: null 
      }; 
   };  
   page.onResourceReceived = function (res) {  
      //当收到任何文件时调用。
      if (res.stage === 'start') { 
         page.resources[res.id].startReply = res; 
      } 
      if (res.stage === 'end') { 
         page.resources[res.id].endReply = res; 
      } 
   };  
   page.open(page.address, function (status) {  // 打开给定的页面网址
      var har; 
      
      if (status !== 'success') { 
         console.log('FAIL to load the address'); 
         phantom.exit(1); 
      } else { 
         page.endTime = new Date(); 
         
         page.title = page.evaluate(function () { // 获取页面标题
            return document.title; 
         });             
         har = createHAR(page.address, page.title, page.startTime, page.resources);  
         
        // 使用页面 URL、开始时间和页面资源调用 createHAR 函数。
        // console.log(JSON.stringify(har, undefined, 4));
        fs.write('log.txt', JSON.stringify(har, undefined, 4), 'w');
        
        // 日志收集在 log.txt 文件中。
        phantom.exit();
      } 
   }); 
}

提供给 HAR 预览的 log.txt 示例

{ 
   "log": { 
      "version": "1.2", 
      "creator": { 
         "name": "PhantomJS", 
         "version": "2.1.1" 
      }, 
      "pages": [ 
         { 
            "startedDateTime": "2017-05-21T13:41:21.824Z", 
            "id": "http://www.sample.com", 
            "title": "Free Sample Products – Sample.com ≫ Free Samples, 
               Free Product Samples, Product Test Marketing", 
            "pageTimings": { 
               "onLoad": 11081 
            } 
         } 
      ], 
      "entries": [ 
         { 
            "startedDateTime": "2017-05-21T13:41:21.815Z", 
            "time": 1999, 
            
            "request": { 
               "method": "GET", 
               "url": "http://www.sample.com/", 
               "httpVersion": "HTTP/1.1", 
               "cookies": [], 
               
               "headers": [ 
                  { 
                     "name": "Accept", 
                     "value": "text/html,application/xhtml+xml,
                        application/xml;q = 0.9,*/*;q = 0.8" 
                  }, 
                  
                  { 
                     "name": "User-Agent", 
                     "value": "Mozilla/5.0 (Windows NT 6.2; WOW64) AppleWebKit/538.1 
                        (KHTML, like Gecko) PhantomJS/2.1.1 Safari/538.1"  
                  } 
               ], 
               
               "queryString": [], 
               "headersSize": -1, 
               "bodySize": -1 
            }, 
            "response": { 
               "status": 301, 
               "statusText": "Moved Permanently", 
               "httpVersion": "HTTP/1.1", 
               "cookies": [], 
               
               "headers": [ 
                  { 
                     "name": "Date", 
                     "value": "Sun, 21 May 2017 13:41:25 GMT" 
                  }, 
                  
                  { 
                     "name": "Server", 
                     "value": "Apache/2.2.14 (Ubuntu)" 
                  }, 
                  
                  { 
                     "name": "Location", 
                     "value": "http://sample.com//" 
                  }, 
                  
                  { 
                     "name": "Vary", 
                     "value": "Accept-Encoding" 
                  }, 
                  
                  { 
                     "name": "Content-Encoding", 
                     "value": "gzip" 
                  }, 
                  
                  { 
                     "name": "Keep-Alive", 
                     "value": "timeout = 15, max = 100" 
                  },
                  
                  { 
                     "name": "Connection", 
                     "value": "Keep-Alive" 
                  }, 
                  
                  { 
                     "name": "Content-Type", 
                     "value": "text/html; charset = iso-8859-1" 
                  } 
               ],  
               "redirectURL": "", 
               "headersSize": -1, 
               "bodySize": 307, 
               
               "content": { 
                  "size": 307, 
                  "mimeType": "text/html; charset = iso-8859-1" 
               } 
            }, 
            
            "cache": {}, 
            "timings": { 
               "blocked": 0, 
               "dns": -1, 
               "connect": -1, 
               "send": 0, 
               "wait": 1999, 
               "receive": 0, 
               "ssl": -1 
            }, 
            "pageref": "http://www.sample.com" 
         }, 
      ]   
      { 
         "startedDateTime": "2017-05-21T13:41:24.898Z", 
         "time": 885, 
         
         "request": { 
            "method": "GET", 
            "url": "http://sample.com/", 
            "httpVersion": "HTTP/1.1", 
            "cookies": [], 
            
            "headers": [ 
               { 
                  "name": "Accept", 
                  "value": "text/html,application/xhtml+xml,
                     application/xml;q = 0.9,*/*;q = 0.8" 
               }, 
               
               { 
                  "name": "User-Agent", 
                  "value": "Mozilla/5.0 (Windows NT 6.2; WOW64) AppleWebKit/538.1 
                     (KHTML, like Gecko) PhantomJS/2.1.1 Safari/538.1" 
               } 
            ], 
            "queryString": [], 
            "headersSize": -1, 
            "bodySize": -1 
         }, 
         "response": { 
            "status": 200, 
            "statusText": "OK", 
            "httpVersion": "HTTP/1.1", 
            "cookies": [], 
            
            "headers": [ 
               { 
                  "name": "Date", 
                  "value": "Sun, 21 May 2017 13:41:27 GMT" 
               }, 
               
               { 
                  "name": "Server", 
                  "value": "Apache/2.2.14 (Ubuntu)" 
               }, 
               
               { 
                  "name": "X-Powered-By", 
                  "value": "PHP/5.3.2-1ubuntu4.29" 
               }, 
               
               {
                  "name": "X-Pingback", 
                  "value": "http://sample.com/xmlrpc.php" 
               }, 
               
               { 
                  "name": "Link", 
                  "value": "<http://sample.com/wp-json/>; 
                     rel = \"https://api.w.org/\", <http://wp.me/P6Jj5H-4>; 
                     rel = shortlink" 
               }, 
               
               { 
                  "name": "Vary", 
                  "value": "Accept-Encoding"  
               }, 
               
               { 
                  "name": "Content-Encoding",
                  "value": "gzip" 
               },

               { 
                  "name": "Keep-Alive",
                  "value": "timeout = 15, max = 99"
               },

               {
                  "name": "Connection",
                  "value": "Keep-Alive"
               },

               { 
                  "name": "Content-Type",
                  "value": "text/html; charset = UTF-8"
               }
            ],

            "redirectURL": "",
            "headersSize": -1,
            "bodySize": 1969,

            "content": {
               "size": 1969,
               "mimeType": "text/html; charset = UTF-8"
            }
         },

         "cache": {},
         "timings": {
            "blocked": 0,
            "dns": -1,
            "connect": -1,
            "send": 0,
            "wait": 869,
            "receive": 16,
            "ssl": -1
         },

         "pageref": http://www.sample.com
      },

      {
         "startedDateTime": "2017-05-21T13:41:25.767Z",
         "time": 388,

         "request": {
            "method": "GET",
            "url": "http://sample.com/wpcontent/themes/samplecom/style.css",
            "httpVersion": "HTTP/1.1",
            "cookies": [],

            "headers": [
               {
                  "name": "Accept",
                  "value": "text/css,*/*;q = 0.1"
               },

               {
                  "name": "Referer",
                  "value": "http://sample.com/"
               },

               {
                  "name": "User-Agent",
                  "value": "Mozilla/5.0 (Windows NT 6.2; WOW64) AppleWebKit/538.1 
                     (KHTML, like Gecko) PhantomJS/2.1.1 Safari/538.1"
               }
            ],

            "queryString": [],
            "headersSize": -1,
            "bodySize": -1
         },

         "response": {
            "status": 200,
            "statusText": "OK",
            "httpVersion": "HTTP/1.1",
            "cookies": [],

            "headers": [
               {
                  "name": "Date",
                  "value": "Sun, 21 May 2017 13:41:27 GMT"
               },

               {
                  "name": "Server",
                  "value": "Apache/2.2.14 (Ubuntu)"
               },

               {
                  "name": "Last-Modified",
                  "value": "Fri, 22 Apr 2011 00:32:22 GMT"
               },

               {
                  "name": "ETag",
                  "value": "\"e1d7-1836-4a176fdbbd180\""
               },

               {
                  "name": "Accept-Ranges",
                  "value": "bytes"
               },

               {
                  "name": "Vary",
                  "value": "Accept-Encoding"
               },

               {
                  "name": "Content-Encoding",
                  "value": "gzip"
               },

               {
                  "name": "Keep-Alive",
                  "value": "timeout = 15, max = 98"
               },

               {
                  "name": "Connection",
                  "value": "Keep-Alive"
               },

               {
                  "name": "Content-Type",
                  "value": "text/css"
               }
            ],

            "redirectURL": "",
            "headersSize": -1,
            "bodySize": 3174,
            
            "content": {
               "size": 3174,
               "mimeType": "text/css"
            }
         },

         "cache": {},
         "timings": {
            "blocked": 0,
            "dns": -1,
            "connect": -1,
            "send": 0,
            "wait": 388,
            "receive": 0,
            "ssl": -1
         },
         
         "pageref": "http://www.sample.com"
      }
   }
}

Output

上述程序生成以下输出。

Har Preview

所有日志都收集在 .txt 文件 中,之后使用 HAR 预览将其转换为上述格式,例如 (http://www.softwareishard.com/har/viewer/)

PhantomJS - 测试

PhantomJS 为网页提供了大量 API,可提供所有详细信息。PhantomJS 可用于测试,如获取页面内容、进行屏幕共享、将页面转换为 pdf 等。市场上有许多流行的测试库,可与 PhantomJS 一起使用并用于测试。

一些可与 PhantomJS 配合使用的流行框架如下 −

  • Mocha
  • Jasmine
  • Qunit
  • Hiro
  • Laika
  • Buster.JS
  • WebDriver

示例 - PhantomJS 与 Qunit

(function () {     
   var url, timeout,args = require('system').args, page = require('webpage').create(); 
   url = args[1]; 
   timeout = parseInt(10, 10); 
   
   page.onConsoleMessage = function (msg) {  
      //打印所有控制台消息
      console.log(msg); 
   }; 
   page.onInitialized = function () {  // 在页面初始化时调用
      page.evaluate(callqunit); 
   }; 
   page.onCallback = function (message) { // called from  
      var result, failed; 
      
      if (message) {  
         if (message.name === 'QUnit.done') { 
            result = message.data; 
            failed = !result || !result.total || result.failed;  
            
            if (!result.total) { 
               console.error('No tests were executed'); 
            } 
            pageexit(failed ? 1 : 0); 
         } 
      } 
   };  
   page.open(url, function (status) { // opening page  
      if (status !== 'success') { 
         console.error('Unable to access network: ' + status); 
         pageexit(1); 

      } else { 
         var checkqunit = page.evaluate(function () { 
            //评估页面并检查是否为 qunit 对象
               is present on the given page url 
            return (typeof QUnit === 'undefined' || !QUnit); 
         }); 
         
         if (checkqunit) { 
            console.error('Qunit scripts are not present on the page'); 
            pageexit(1); 
         }             
         
         //使用 10 秒的超时时间,否则将打印来自控制台的消息。
         setTimeout(function () { 
            console.error('The specified timeout of ' + timeout + ' seconds has expired. 
               Aborting...'); 
            pageexit(1); 
         }, timeout * 1000);           
      } 
   });  
   function callqunit() {

qunit.html

<!DOCTYPE html> 
<html> 

   <head> 
      <meta charset = "utf-8"> 
      <meta name = "viewport" content = "width = device-width"> 
      <title>QUnit Example</title> 
      <link rel = "stylesheet" href = "https://code.jquery.com/qunit/qunit-2.3.2.css"> 
   </head> 

   <body> 
      <div id = "qunit"></div> 
      <div id = "qunit-fixture"></div> 
      <script src = "https://code.jquery.com/qunit/qunit-2.3.2.js"></script> 
   </body> 
   
</html> 

输出

命令 − phantomjs qunit.js http://localhost/tasks/qunit.html

上述程序生成以下输出。

{"passed":3,"failed":2,"total":5,"runtime":23}
Time taken is 23ms to run 5 tests.
3 passed, 2 failed.

PhantomJS - REPL

REPL 代表 Read Eval Print Loop。在 PhantomJS 中,REPL 是一种测试 JavaScript 代码的交互模式。您可以执行与在 Google Chrome Inspector 或 Firebug 中相同的操作,以直接在控制台上执行某些代码。REPL 返回相同的平台来执行脚本。

输入的命令将发送到解释器进行立即解释(EVAL)并提供反馈(PRINT)。在命令行中输入 PhantomJS,它将带您进入交互模式,您可以在其中直接执行代码。

语法

其语法如下 −

Phantomjs

示例

以下示例演示了 REPL 在 PhantomJS 中的工作方式。

phantomjs> console.log("Welcome to phantomjs");
Welcome to phantomjs
Undefined

phantomjs> window.navigator {
   "appCodeName": "Mozilla",
   "appName": "Netscape",
   "appVersion": "5.0 (Windows NT 6.2; WOW64) AppleWebKit/538.1 (KHTML, like Gecko)
      PhantomJS/2.1.1 Safari/538.1",
   "cookieEnabled": true,
   "language": "en-IN",

   "mimeTypes": {
      "length": 0
   },
   "onLine": false,
   "platform": "Win32",

   "plugins": {
      "length": 0
   },
   "product": "Gecko
   "productSub": "20030107",
   "userAgent": "Mozilla/5.0 (Windows NT 6.2; WOW64) AppleWebKit/538.1 (KHTML, like Gecko)
      PhantomJS/2.1.1 Safari/538.1",
   "vendor": "Apple Computer, Inc.",
   "vendorSub": ""
}

phantomjs>
To find the version
phantomjs> phantom.version {
   "major": 2,
   "minor": 1,
   "patch": 1
}
phantomjs>

执行每个命令并显示结果。使用 CTRL+C、CTRL+D 或 phantom.exit() 退出交互模式。

使用 向上/向下 箭头键收听先前输入的命令。

还有另一个称为 自动完成 的功能,它有助于记住命令。只需输入"phantom"并点击"Tab"按钮即可获得可执行的可用命令列表。

输出

上述程序生成以下输出。

phantomjs> phantom.→| 
phantomjs> phantom.cookies→| 
phantomjs> phantom.exit→| 
phantomjs> phantom.version→|

PhantomJS - 示例

在本章中,我们将提供一些更实际的示例来帮助您了解 PhantomJS 的一些重要功能。

示例 1 - 查找页面速度

在此示例中,我们将使用 PhantomJS 查找任何给定页面 URL 的页面速度

var page = require('webpage').create(), 
   system = require('system'), 
   t, address;  

if (system.args.length === 1) { 
   console.log('Usage: loadspeed.js <some URL>'); 
   phantom.exit(1); 
} else { 
   t = Date.now(); 
   address = system.args[1]; 
   
   page.open(address, function (status) { 
      if (status !== 'success') { 
         console.log('FAIL to load the address'); 
      } else { 
         t = Date.now() - t; 
         
         console.log('Page title is ' + page.evaluate(function () { 
            return document.title; 
         })); 
         console.log('Loading time ' + t + ' msec'); 
      } 
      phantom.exit(); 
   }); 
}

上述程序生成以下输出

命令 − phantomjs pagespeed.js http://www.google.com

Page title is Google 
Loading time 1396 msec 

示例 2 - 向页面发送点击事件

在下面的示例中,我们将使用 PhantomJS 向页面发送 点击事件

var page = require('webpage').create(); 
page.onConsoleMessage = function(str) { 
   console.log(str); 
} 
page.open('http://phantomjs.org/api/phantom/', function(status) { 
   page.render('beforeclick.png'); 
   console.log(page.url); 
   
   var element = page.evaluate(function() {   
      return document.querySelector('img[src = "http://phantomjs.org/img/phantomjslogo.png"]'); 
   }); 
   page.sendEvent('click', element.offsetLeft, element.offsetTop, 'left'); 
   
   window.setTimeout(function () { 
      console.log(page.url); 
      page.render('afterclick.png'); 
      phantom.exit(); 
   }, 5000); 
   console.log('element is ' + element); 
}); 

上述程序生成以下输出

http://phantomjs.org/api/phantom/ 
element is [object Object] 
http://phantomjs.org/

我们的程序将在 bin 文件夹中创建以下两个 png 图像。这两幅图像显示了上述程序执行前后的差异。

点击前 最佳解决方案

示例 3 - 提交表单

以下示例显示如何使用 PhantomJS 提交表单。

var wpage = require('webpage').create();  
wpage.open("http://localhost/tasks/submitform.html", function(status) { 
   console.log(status); 
   wpage.uploadFile('input[name = fileToUpload]', 'output.png'); 
   wpage.render("sform.png");  
   
   var element = wpage.evaluate(function() {   
      return document.querySelector('input[type = "submit"]');   
      // 使用 queryselector 获取提交按钮的详细信息。
   }); 
   wpage.sendEvent('click', element.offsetLeft, element.offsetTop, 'left');  
   
   // sendevent 用于发送点击事件,并给出左侧和顶部
      position of the submit button. 
   
   window.setTimeout(function () { 
      console.log(wpage.url); 
      wpage.render("submit.png");  // 截图保存在submit.png中
      phantom.exit(); 
   }, 5000);  
   console.log('element is ' + element);  
});

submitform.html

以下代码显示如何使用 submitform.html 文件。

<html> 
   <head>
      <title>Window 2</title>
   </head> 

   <body>
      <form action = "submitform.php" method = "post" enctype = "multipart/form-data" 
         id = "form1">  
         <input type = "file" name = "fileToUpload" id = "fileToUpload"> 
         <input type = "submit" value = "Upload Image" name = "submit"> 
      </form> 
   </body>  
   
</html>

表单提交后,将转到 submitform.php

submitform.php

submitform.php 仅打印文件的详细信息。

<?php 
   print_r($_FILES); 
?> 

上述程序生成以下输出

Success 
element is [object Object] 
http://localhost/tasks/submitform.php 

图片

以下是文件上传表单提交的图片。

文件上传 表单提交