如何为搜索引擎优化 PhantomJS 以索引单页应用程序?

Posted

技术标签:

【中文标题】如何为搜索引擎优化 PhantomJS 以索引单页应用程序?【英文标题】:How to optimize PhantomJS for search engines to index a single page application? 【发布时间】:2013-07-28 21:46:24 【问题描述】:

我一直在寻找可以在服务器上运行的无头网络浏览器,以便网络爬虫索引单页应用程序。首先,我尝试了 htmlUnit 和 Selenium (HtmlUnitDriver),但似乎它们都有 xhr 请求的问题。

我发现 PhantomJS 性能更好,看起来很成熟。 PhantomJS 有一个internal webserver,所以我决定将它与我的反向代理一起使用。但是我运行了一个基准测试,PhantomJS 达到了 100% 的 cpu 核心,平均页面加载时间约为 4 秒。原因是我必须等待浏览器加载所有资源才能获得正确的结果。这是我的 PhantomJS 脚本:

var page = require('webpage');
var system = require('system');
var server = require('webserver').create();

// credit: http://backbonetutorials.com/seo-for-single-page-apps/
var service = server.listen(port,  'keepAlive': true , function(z, response) 
    var request = page.create();
    var lastReceived = new Date().getTime();
    var requestCount = 0;
    var responseCount = 0;
    var requestIds = [];
    var startTime = new Date().getTime();
    request.onResourceReceived = function (response) 
        if (requestIds.indexOf(response.id) !== -1) 
            lastReceived = new Date().getTime();
            responseCount++;
            requestIds[requestIds.indexOf(response.id)] = null;
        
    ;
    request.onResourceRequested = function (request) 
        if (requestIds.indexOf(request.id) === -1) 
            requestIds.push(request.id);
            requestCount++;
        
    ;
    request.settings =  
      loadImages: false, 
      javascriptEnabled: true,
      loadPlugins: false 
    ;
    request.open(z.url, function (status, a) 
        if (status !== 'success') 
            console.log('FAIL to load the address '+a);
        
    );
    var checkComplete = function () 
        var now = new Date().getTime();
        if ((now - lastReceived > 300 && requestCount === responseCount) || now - startTime > 5000) 
            clearInterval(checkCompleteInterval);
            response.statusCode = 200;
            response.headers = 
                'Cache': 'no-cache',
                'Content-Type': 'text/html; charset=UTF-8',
                'Connection': 'Keep-Alive',
                'Keep-Alive': 'timeout=5, max=100',
                'Content-Length': request.content.length
            ;
            response.write(request.content);
            response.close();
            request.release();
            console.log(request.url+" -> "+(now - startTime));
        
    
    var checkCompleteInterval = setInterval(checkComplete, 3);

);

是否有任何改进可以加快脚本的速度,我应该只使用其 shell 命令运行 PhantomJS 以获得更好的性能,还是这些浏览器有任何替代方案?

【问题讨论】:

【参考方案1】:

您可以使用一些command line switches 来提高捕获性能:

首先,您可以忽略所有带有--load-images=no 的图像。进行 HTML 快照时无需加载图像。

您还可以使用--disk-cache=yes 启用缓存(使用--max-disk-cache-size 以字节为单位设置其大小)

最后,WebPage#onResourceRequested 回调对于使用NetworkRequest#abort 方法中止一些请求(跟踪器、媒体文件...)也很有用。

【讨论】:

嗯,我没有看到您已经将 loadImages 设置为 false,因此不需要第一个建议。 感谢 NetworkRequest#abort 提示。在这种情况下,Facebook API 和分析 API 不是必需的,现在脚本似乎更快了。

以上是关于如何为搜索引擎优化 PhantomJS 以索引单页应用程序?的主要内容,如果未能解决你的问题,请参考以下文章

如何为MySQL查询优化选择最佳索引

如何为mysql中的现有表创建索引?

如何为单页 AngularJS 应用程序实现基本的 Spring 安全性(会话管理)

如何为 MySQL 表添加索引?

使用索引时如何为 UV 添加 vec2 以进行纹理映射

如何为drupal添加状态代码410以删除内容以改善SEO?