PhantomJS是一个服务器端的 JavaScript API 的 WebKit,支持各种Web标准: DOM 处理, CSS 选择器, JSON, Canvas, SVG

PhantomJS is a headless WebKit scriptable with a JavaScript API. It has fast and native support for various web standards: DOM handling, CSS selector, JSON, Canvas, and SVG.

PhantomJS 介绍

1)一个基于webkit内核的无头浏览器,没有UI界面,即它就是一个浏览器,只是其内的点击、翻页等人为相关操作需要程序设计实现

2)提供JavaScript API接口,即通过编写js程序可以直接与webkit内核交互,在此之上可以结合Java语言等,通过java调用js等相关操作,从而解决了以前c/c++才能比较好的基于webkit开发优质采集器的限制

3)提供Windows、Linux、Mac等不同os的安装使用包,也就是说可以在不同平台上二次开发采集项目或是自动项目测试等工作

PhantomJS 官网: http://phantomjs.org

 

使用场景:

  • 无需浏览器的 Web 测试

  • 页面访问自动化

  • 屏幕捕获

  • 网络监控

屏幕捕获示例代码:

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

 

PhantomJS 生态环境:

  • CasperJS enables easy navigation scripting and common high-level testing.

  • Poltergeist allows running Capybara tests headlessly.

  • Guard::Jasmine automatically tests Jasmine specs on Rails when files are modified.

  • GhostDriver complements Selenium tests with a PhantomJS WebDriver implementation.

  • PhantomRobot runs Robot Framework acceptance tests in the background via PhantomJS.

  • Mocha-PhantomJS run Mocha tests using PhantomJS.

  • 其他一些相关项目

 

PhantomJS 常用API

1)常用内置几大对象

var system = require('system');     // 获得系统操作对象,包括命令行参数、phantomjs系统设置等信息
var page = require('webpage');   // 获取操作dom或web网页的对象,通过它可以打开网页、接收网页内容、request、response参数,其为最核心对象。
var fs = require('fs');    // 获取文件系统对象,通过它可以操作操作系统的文件操作,包括read、write、move、copy、delete等。

 

2) 常用API

page.open(url,function (status) {}    // 通过page对象打开url链接,并可以回调其声明的回调函数,其回调发生的时机为该URL被彻底打开完毕,即该URL所引发的请求项被全部加载完,但ajax请求是与它的加载完成与否没有关系

page.onLoadStarted = function() {}    // 当page.open调用时,回首先执行该函数,在此可以预置一些参数或函数,用于后边的回调函数中

page.onResourceError = function(resourceError) {}    // page的所要加载的资源在加载过程中,出现了各种失败,则在此回调处理

page.onResourceRequested = function(requestData, networkRequest) {}    // page的所要加载的资源在发起请求时,都可以回调该函数

page.onResourceReceived = function(response) {}    // page的所要加载的资源在加载过程中,每加载一个相关资源,都会在此先做出响应,它相当于http头部分,  其核心回调对象为response,可以在此获取本次请求的cookies、userAgent等

page.onConsoleMessage = function (msg) {}    // 欲在执行web网页时,打印一些输出信息到控制台,则可以在此回调显示。

page.onAlert = function(msg) {}    // phantomjs是没有界面的,所以对alert也是无法直接弹出的,故phantomjs以该函数回调在page在执行过程中的alert事件

page.onError = function(msg, trace) {}     // 当page.open中的url,它自己(不包括所引起的其它的加载资源)出现了异常,如404、no route to web site等,都会在此回调显示。

page.onUrlChanged = function(targetUrl) {}     // 当page.open打开的url或是该url在打开过程中基于该URL进行了跳转,则可在此函数中回调。

page.onLoadFinished = function(status){}      //  当page.open的目标URL被真正打开后,会在调用open的回调函数前调用该函数,在此可以进行内部的翻页等操作

page.evaluate(function(){});    // 在所加载的web page内部执行该函数,像翻页、点击、滑动等,均可在此中执行

page.render("");    // 将当前page的现状渲染成图片,输出到指定的文件中去。

 

3)注意事项

  1. 区分phantomjs的对象和打开的web page的对象,如document、window等,两者都有,在调用page.evaluate和不调用的时候,注意区分二者的范围,容易在调试时出现很多的问题,且不好发现。    
  2. page.injectJs和page.includeJs的区别,前者侧重本地的js文件,与libraryPath挂购,后者侧重网络js文件,尤其在引入jQuery等第三方库时,会经常遇到。
  3. 编码问题,两个重要参数,--output-encoding,--script-encoding,前者为输出编码,后者为所使用js、参数配置文件的编码,为方便起鉴,建议均采用utf-8编码,并注所应用到的目标文件的编码,以免引起很不可思议的异常,又无从查起。

 

1. 下载 PhantomJS

官网下载: http://phantomjs.org/download.html

Windows: phantomjs-2.1.1-windows.zip

Mac OS X:phantomjs-2.1.1-macosx.zip (推荐

Linux 64-bit:phantomjs-2.1.1-linux-x86_64.tar.bz2推荐

Linux 32-bit: phantomjs-2.1.1-linux-i686.tar.bz2

FreeBSD: sudo pkg install phantomjs

PhantomJS 源码: https://github.com/ariya/phantomjs/  

 

2. 安装 PhantomJS

PhantomJS不需要安装,解压后,配置环境变量后,便可直接使用

 

3. 配置 PhantomJS

1) macOS PATH 变量

vim /etc/profile

添加如下内容:

PHANTOMJS_HOME=/opt/phantomjs-2.1.1
export PATH=$PHANTOMJS_HOME/bin:$PATH

执行命令,使其生效:

source /etc/profile

验证可用:

$ phantomjs -v
2.1.1

 

2) Windows PATH 变量

在“系统变量”选项区域中查看PATH变量,如果不存在,则新建变量 PATH, 否则选中该变量,

单击“编辑”按钮,在“变量值”文本框的起始位置添加 D:\phantomjs\bin

开始-运行-输入cmd,输入 phantomjs --version

如果可以看到版本号,则安装成功。

 

4. 简单示例

PhantomJS 自带示例目录:

cd /opt/phantomjs-2.1.1/examples

 

hello.js 示例:

"use strict";
console.log('Hello, world!');
phantom.exit();

执行命令,运行结果:

$ phantomjs hello.js 
Hello, world!

 

命令行执行:

$ phantomjs     
phantomjs> console.log('hello mimvp.com'); phantom.exit();
hello mimvp.com

 

爬取网页:

vim spider_web.js

/**
* mimvp.com
* 2017.6.20
*/

var page = require('webpage').create();
page.open('http://mimvp.com', function(status) {
  console.log("Status: " + status);
  if(status === "success") {
  	console.log(page.content);		// 爬取网页内容
  	console.log("page.content length: " + page.content.length);		// 打印网页内容长度
    page.render('http://proxy.mimvp.com');
  }
  phantom.exit();
});

 

模拟登陆示例:

vim login.js

var page = require('webpage').create(),  
    server = 'http://proxy.mimvp.com/login.php',  
    data = 'username=admin&password=xxxxx';  
  
page.open(server, 'post', data, function (status) {  
    if (status !== 'success') {  
        console.log('Unable to post!');  
    } else {  
       console.log(page.content);  
//   page.render('index.png');      
}  
    phantom.exit();  
});  

执行命令:

plantomjs login.js >> index.html

说明:plantomjs非常方便的应用于模拟登陆,如微博、电商类,或是小米、火车票抢票等项目中

 

5. 代理示例

PhantomJS 帮助文档里说明,只支持 http 和 socks5 两种协议类型,不支持 https 和 socks4

如果要访问 http 和 https 网站,推荐 http 访问 http网站,socks5 访问 http 和 https 网站

phantomjs --help

$ phantomjs --help
Usage:
   phantomjs [switchs] [options] [script] [argument [argument [...]]]

Options:
  --cookies-file=<val>                 Sets the file name to store the persistent cookies
  --config=<val>                       Specifies JSON-formatted configuration file
  --debug=<val>                        Prints additional warning and debug message: 'true' or 'false' (default)
  --disk-cache=<val>                   Enables disk cache: 'true' or 'false' (default)
  --disk-cache-path=<val>              Specifies the location for the disk cache
  --ignore-ssl-errors=<val>            Ignores SSL errors (expired/self-signed certificate errors): 'true' or 'false' (default)
  --load-images=<val>                  Loads all inlined images: 'true' (default) or 'false'
  --local-url-access=<val>             Allows use of 'file:///' URLs: 'true' (default) or 'false'
  --local-storage-path=<val>           Specifies the location for local storage
  --local-storage-quota=<val>          Sets the maximum size of the local storage (in KB)
  --offline-storage-path=<val>         Specifies the location for offline storage
  --offline-storage-quota=<val>        Sets the maximum size of the offline storage (in KB)
  --local-to-remote-url-access=<val>   Allows local content to access remote URL: 'true' or 'false' (default)
  --max-disk-cache-size=<val>          Limits the size of the disk cache (in KB)
  --output-encoding=<val>              Sets the encoding for the terminal output, default is 'utf8'
  --remote-debugger-port=<val>         Starts the script in a debug harness and listens on the specified port
  --remote-debugger-autorun=<val>      Runs the script in the debugger immediately: 'true' or 'false' (default)
  --proxy=<val>                        Sets the proxy server, e.g. '--proxy=http://proxy.company.com:8080'
  --proxy-auth=<val>                   Provides authentication information for the proxy, e.g. ''-proxy-auth=username:password'
  --proxy-type=<val>                   Specifies the proxy type, 'http' (default), 'none' (disable completely), or 'socks5'
  --script-encoding=<val>              Sets the encoding used for the starting script, default is 'utf8'
  --script-language=<val>              Sets the script language instead of detecting it: 'javascript'
  --web-security=<val>                 Enables web security, 'true' (default) or 'false'
  --ssl-protocol=<val>                 Selects a specific SSL protocol version to offer. Values (case insensitive): TLSv1.2, TLSv1.1, TLSv1.0, TLSv1 (same as v1.0), SSLv3, or ANY. Default is to offer all that Qt thinks are secure (SSLv3 and up). Not all values may be supported, depending on the system OpenSSL library.
  --ssl-ciphers=<val>                  Sets supported TLS/SSL ciphers. Argument is a colon-separated list of OpenSSL cipher names (macros like ALL, kRSA, etc. may not be used). Default matches modern browsers.
  --ssl-certificates-path=<val>        Sets the location for custom CA certificates (if none set, uses environment variable SSL_CERT_DIR. If none set too, uses system default)
  --ssl-client-certificate-file=<val>  Sets the location of a client certificate
  --ssl-client-key-file=<val>          Sets the location of a clients' private key
  --ssl-client-key-passphrase=<val>    Sets the passphrase for the clients' private key
  --webdriver=<val>                    Starts in 'Remote WebDriver mode' (embedded GhostDriver): '[[:]]' (default '127.0.0.1:8910') 
  --webdriver-logfile=<val>            File where to write the WebDriver's Log (default 'none') (NOTE: needs '--webdriver') 
  --webdriver-loglevel=<val>           WebDriver Logging Level: (supported: 'ERROR', 'WARN', 'INFO', 'DEBUG') (default 'INFO') (NOTE: needs '--webdriver') 
  --webdriver-selenium-grid-hub=<val>  URL to the Selenium Grid HUB: 'URL_TO_HUB' (default 'none') (NOTE: needs '--webdriver') 
  -w,--wd                              Equivalent to '--webdriver' option above
  -h,--help                            Shows this message and quits
  -v,--version                         Prints out PhantomJS version

Any of the options that accept boolean values ('true'/'false') can also accept 'yes'/'no'.

Without any argument, PhantomJS will launch in interactive mode (REPL).

Documentation can be found at the web site, http://phantomjs.org.

如上,代理参数分别为: 

  --proxy=<val>                        Sets the proxy server, e.g. '--proxy=http://proxy.company.com:8080'
  --proxy-auth=<val>                   Provides authentication information for the proxy, e.g. ''-proxy-auth=username:password'
  --proxy-type=<val>                   Specifies the proxy type,
'http' (default), 'none' (disable completely), or 'socks5'

 

PhantomJS 代理示例,由两部分组成,分别是爬取网页代码和使用代理命令(采用米扑代理,测试成功)

1) 爬取网页代码

/**
* proxy.mimvp.com
* 2017.6.22
*
* http 	  : phantomjs --proxy-type=http --proxy=138.68.161.157:8080 mimvp-phantomjs.js 
* socks5  : phantomjs --proxy-type=socks5 --proxy=82.209.150.212:45454 mimvp-phantomjs.js
*/

var page = require('webpage').create();
page.settings.userAgent = 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12_3) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/59.0.3071.115 Safari/537.36';

// page.open("http://proxy.mimvp.com/exist.php", {}, function(status) {
page.open("https://apps.bdimg.com/libs/jquery-i18n/1.1.1/jquery.i18n.min.js", {}, function(status) {
  	console.log('status : ' + status);
	if(status == "success") {
		console.log("set proxy success");
		console.log('page.content : ' + page.content);
		console.log('page.content length : ' + page.content.length);
	} else {
		console.log("set proxy fail");
	}
  	
  phantom.exit();
}); 

 

2)使用代理命令

http 协议的执行命令:

phantomjs --proxy-type=http --proxy=138.68.161.157:8080 mimvp-phantomjs.js 

 

socks5 协议的执行命令:

phantomjs --proxy-type=socks5 --proxy=82.209.150.212:45454 mimvp-phantomjs.js

 

测试代理来自米扑代理(推荐): 

http://proxy.mimvp.com

 

 

参考推荐

PhantomJS 安装

Node.js 安装与开发

Nodejs SuperAgent 安装与开发

Node.js 设置代理的两种方式:superagent-proxy 和 https-proxy-agent

米扑代理使用示例史上最全最权威的代理使用示例

Python使用Selenium和PhantomJS解析动态JS的网页

Python+Selenium2 搭建自动化测试环境