Phantomjs正确使用方式
正确打开方式应该使用phantomjs Webservice作为一种web服务的形式(api),将其与其他语言分离开来(比如python)。
设计流程:
Python通过http请求下发任务,Phantomjs Webservice获取任务后去处理,处理完以后再将结果返回给Python。任务调度、存储等复杂操作交给Python去做,Python可以写成异步并发去请求Phantomjs Webservice,需要注意的是目前一个Phantomjs Webservice只支持10个并发。但我们可以在一台服务器上多开几个phantomjs Webservice启用不同的端口即可,或者可以多台服务器做个集群,用nginx做反向代理。
Phantomjs Webservice
新建test.js,写入如下代码:
//此js用来获取网页源码
var system=require('system'); //get args
var args=system.args;
if(args.length ===2){
var port=Number(args[1]);
}
else{
var port=8080;
}
var webserver = require('webserver');
var server = webserver.create()
var service = server.listen(port,function(request, response) {
try{
var postRaw=request.postRaw;
var aaa=new Array();
aaa=postRaw.split("=");
var url=aaa[0];
var md5_url=aaa[1];
url=decodeURIComponent(url);
// 创建page
var webPage = require('webpage');
var page = webPage.create();
page.settings.resourceTimeout = 20000;//timeout is 20s
// 页面错误捕捉
page.onError =function(msg, trace) {
console.log("[Warning]This is page.onError");
var msgStack = ['ERROR: '+ msg];
if(trace && trace.length) {
msgStack.push('TRACE:');
trace.forEach(function(t) {
msgStack.push(' -> '+ t.file +': '+ t.line + (t.function ?' (in function "'+ t.function +'")':''));
});
}
// console.error(msgStack.join('\n'));
};
// phantomjs错误捕捉
phantom.onError =function(msg, trace) {
console.log("[Warning]This is phantom.onError");
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);
};
// 打开网页,获取源码
page.open(url,function(status) {
console.log('Target_url is '+ url); //输出待检测的网站url
if(status=='success'){
var current_url = page.url;
var body= page.content;
}
else
{
var body="";
var current_url="";
}
response.status=200;
// response.write(body); //返回获取到的网页源码
response.write(current_url); //返回当前的网页url
page.close();
response.close();
});
}
catch(e)
{
console.log('[Error]'+e.message+'happen'+e.lineNumber+'line');
}
});
作用:处理http请求,获取url,进行截图或者获取源码操作。
使用:
1phantomjs.exe test.js 8080
会在本地开启web服务,端口为8080。
Python Client
新建http_request.py,写入如下代码:
#! -*- coding:utf-8 -*-
import requests
import hashlib
import base64
from multiprocessing.dummy import Pool
class http_request:
def __init__(self,port="8080"):
self.url="http://localhost:"+port
def getwebbody(self,domain):
'''
获取网页源代码
'''
base_domain=base64.b64encode(domain)
md5_domain=hashlib.md5(base_domain).hexdigest()
payload={domain:md5_domain}
try:
response=requests.post(self.url,data=payload,timeout=30).content
returnresponse
except requests.exceptions.ConnectionError:
print"requests connection error"
except Exception,e:
printe
return
if__name__=="__main__":
port="8080"
cur=http_request(port)
domain_list=["http://thief.one"]*10
deftest(domain):
print"Result_url is ",cur.getwebbody(domain)
pool = Pool(processes=10)
fordomainindomain_list:#并发下发任务
pool.apply_async(test, args=(domain,))#维持执行的进程总数为10,当一个进程执行完后添加新进程.
pool.close()
pool.join()
作用:异步并发下发任务。
运行截图
运行python以后,异步下发10个任务,Phantomjs服务器端接收到url并开始处理,并发处理10个任务并输入结果。
异常处理
现象:截图为黑屏
原因:网页还没加载完,就开始截图了
解决:在代码中open以后判断status值,判断网页是否加载完毕。
现象:程序出错–windows报错
解决:更换最新版本的phantomjs
现象:内存占用过大,导致报错停止phantomjs进程
原因:phantomjs没有释放内容
解决:代码中open以后,要open.close();
现象:没有截图成功
原因:用了page.close,因为onloadfinished是非阻塞的,因此要将page.close放在open代码层内部。