Phantomjs服务模式:从性能并发方面谈起

8 篇文章 0 订阅
7 篇文章 0 订阅

  作为比较好的动态网页爬虫手段,phantomjs在许多方面令人比较满意。调用Phantomjs的方式,一般有如下几种情况。

命令行模式

  在CMD或Shell中,直接输入phantomjs回车,进入命令行模式,能够完成各种操作。但一般情况是通过命令用调用phantomjs来完成爬虫或模拟工作,具体的代码放在JS中。如

../bin/phantomjs --debug=yes ./server.js 8910
../bin/phantomjs --debug=yes ./hello.js 

其中phantomjs参数直接放在phantomjs后面,脚本作为参数放在其次,最后添加脚本的参数列表。

selenium调用

  selenium是一套完整的测试爬虫工具,能够调用IE、Chrome、Firefox等浏览器内核API完成相应的功能,也可以调用如Phantomjs、HtmlUnitDriver等模拟浏览器作为调用接口。

  调用浏览器内核与不调用浏览器内核的浏览器[这里指的是HtmlUnitDriver],浏览器内核的API,可以完成截图功能及其他浏览器功能,但HtmlunitDriver采用的是JS模拟浏览器的策略,因此不具备截图等浏览器功能。

Java+selenium+Phantomjs调用

public static PhantomJSDriver getPhantomJs(String phantomJS,
        String userAgent, boolean loadImages, boolean jsEnabled,
        String encoding,boolean proxyEnabled,String... proxys) {

    System.setProperty("phantomjs.binary.path", phantomJS);
    DesiredCapabilities desiredCapabilities = DesiredCapabilities
            .phantomjs();
    if (userAgent != null) {
        desiredCapabilities.setCapability(
                "phantomjs.page.settings.userAgent", userAgent);
        desiredCapabilities.setCapability(
                "phantomjs.page.customHeaders.User-Agent", userAgent);
    }
    desiredCapabilities.setJavascriptEnabled(jsEnabled);
    PhantomJSDriver driver = null;
    List<String> cli = new ArrayList<>();
    cli.add("--load-images=" + loadImages);
    cli.add("--output-encoding=" + encoding);

    if (proxyEnabled) {
        String proxy_ip = proxys[0];
        String proxy_port = proxys[1];
        String proxy_user = proxys[2];
        String proxy_pass = proxys[3];
        cli.add("--proxy="+proxy_ip+":"+ proxy_port));
        cli.add("--proxy-auth=" +proxy_user+":" +proxy_pass);
    }
    desiredCapabilities.setCapability(
            PhantomJSDriverService.PHANTOMJS_CLI_ARGS, cli);
    driver = new PhantomJSDriver(desiredCapabilities);
    driver.manage().timeouts()
            .implicitlyWait(WAIT_TIME, TimeUnit.MILLISECONDS);
    driver.manage().deleteAllCookies();

    return driver;
}

Java+selenium+HtmlunitDriver调用

public static HtmlUnitDriver getHtmlUnitDriver(String userAgent,
            boolean jsEnabled, boolean loadImages, boolean proxyEnabled,
            String... proxys) {

        DesiredCapabilities desiredCapabilities = DesiredCapabilities
                .htmlUnit();
        desiredCapabilities.setCapability("phantomjs.page.settings.loadImages",
                false);
        desiredCapabilities.setJavascriptEnabled(jsEnabled);
        if (userAgent != null) {
            desiredCapabilities.setCapability(
                    "phantomjs.page.settings.userAgent", userAgent);
            desiredCapabilities.setCapability(
                    "phantomjs.page.customHeaders.User-Agent", userAgent);
        }
        desiredCapabilities.setCapability(
                PhantomJSDriverService.PHANTOMJS_CLI_ARGS,
                new String[] { "--load-images=" + loadImages });
        HtmlUnitDriver driver = null;
        if (proxyEnabled) {

            String proxy_ip = proxys[0];
            String proxy_port = proxys[1];
            String proxy_user = proxys[2];
            String proxy_pass = proxys[3];

            Proxy proxy = new Proxy();
            proxy.setHttpProxy(proxy_ip + ":" + proxy_port);
            desiredCapabilities.setCapability(CapabilityType.PROXY, proxy);
            driver = new HtmlUnitDriver(desiredCapabilities) {
                @Override
                protected WebClient modifyWebClient(WebClient client) {
                    DefaultCredentialsProvider creds = new DefaultCredentialsProvider();
                    creds.addCredentials(proxy_user, proxy_pass);
                    client.setCredentialsProvider(creds);
                    return client;
                }
            };
        } else
            driver = new HtmlUnitDriver(desiredCapabilities);
        driver.manage().timeouts()
                .implicitlyWait(10 * 1000, TimeUnit.MILLISECONDS);
        driver.manage().deleteAllCookies();

        return driver;
    }

服务器模式

  phantomjs服务器模式,需要在服务端开启服务,然后在客户端发起Http请求然后返回想要的内容,就是一个C/S模式的服务。

服务端

server.js内容如下所示

var webserver = require('webserver').create();
var page = require('webpage').create();
var system = require('system');
var port = system.args[1];
webserver.listen(system.args[1], function(request, response) {
    var url = request.headers.url;// conf target url in headers
    page.open(url, function(status) {
        var title = page.evaluate(function() {
            return $(":root").html();// return pageSource
        });
        response.write(title);
        response.close();
    });
});

命令行启动

bin/phantomjs example/server.js 8910

客户端

在客户端发起http请求,无论是get,还是post只要能够获取到Headers里面的目标URL,就可以返回pageSource。当然,这里最好使用异步加载网页内容。

Map<String, String> params = new HashMap<String, String>();
params.put("url", targetURL);

public static String HttpPost(String url, String postDataStr)
            throws MalformedURLException, IOException {

        URLConnection conn = new URL(url).openConnection();
        conn.addRequestProperty("method", "post");
        conn.addRequestProperty("ContentType",
                "application/x-www-form-urlencoded");
        conn.addRequestProperty("method", "post");
        conn.addRequestProperty("http.socket.timeout", "60000");

        conn.setDoOutput(true);
        conn.getOutputStream().write(
                URLEncoder.encode(postDataStr, "utf-8").getBytes());

        StringBuilder sb = new StringBuilder();
        BufferedReader br = new BufferedReader(new InputStreamReader(
                conn.getInputStream()));
        String line = null;
        while ((line = br.readLine()) != null)
            sb.append(line);

        return sb.toString();
    }

比较

方式优点缺点
命令行模式1、调用简单1、需要配合JS
2、无法大规模并发控制
服务器模式1、减少内存
2、客户端方便
1、存在并发限制,最多10个线程
2、试验产品,可能存在安全隐患
selenium调用1、客户端精准控制
2、调用比较方面,无需写JS
3、可大规模并发
1、“吃”内存:内存随线程数增加较快
2、需手动释放内存,确保phantomjs释放

  1. 由于目前phantomjs已停止更新维护,所以可以选择其他带有webkit内核的模拟浏览器,如Headless Chrome等作为测试/爬虫的首选。
  2. phantomjs使用代理,最好使用无密码代理。

参考

  1. Phantomjs正确打开方式
  2. Phantomjs 进程通信方式
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值