使用 PhantomJS 和 node.js 保存和渲染网页

Posted

技术标签:

【中文标题】使用 PhantomJS 和 node.js 保存和渲染网页【英文标题】:Save and render a webpage with PhantomJS and node.js 【发布时间】:2012-04-15 13:07:00 【问题描述】:

我正在寻找一个请求网页,等待 javascript 呈现(JavaScript 修改 DOM),然后抓取页面的 html 的示例。

这应该是一个简单的例子,带有明显的 PhantomJS 用例。我找不到一个像样的例子,文档似乎都是关于命令行使用的。

【问题讨论】:

您是在做这个客户端还是服务器端? @DeclanCook 服务器端我想?客户端会要求用户安装幻像吗?如果我理解正确,这是行不通的。谢谢 拥有 html 后,您打算用它做什么?试图让我了解你想要实现的目标。 Phantomjs 有 dom 操作,请参阅 code.google.com/p/phantomjs/wiki/QuickStart#DOM_Manipulation 然后你打算把它发送到某个地方吗? @DeclanCook 用例正在为搜索引擎创建 javascript 应用程序视图的缓存静态 html 副本。我希望能够以编程方式运行我的站点地图,并保存每个链接的 html 版本。 @DeclanCook 是的,链接页面是我需要的那种东西,我只是想要一个如何从节点做的例子。谢谢 【参考方案1】:

使用phantomjs-node 的 v2,在处理完 HTML 后打印 HTML 非常容易。

var phantom = require('phantom');

phantom.create().then(function(ph) 
  ph.createPage().then(function(page) 
    page.open('https://***.com/').then(function(status) 
      console.log(status);
      page.property('content').then(function(content) 
        console.log(content);
        page.close();
        ph.exit();
      );
    );
  );
);

这将显示在浏览器中呈现的输出。

2019 年编辑:

你可以使用async/await:

const phantom = require('phantom');

(async function() 
  const instance = await phantom.create();
  const page = await instance.createPage();
  await page.on('onResourceRequested', function(requestData) 
    console.info('Requesting', requestData.url);
  );

  const status = await page.open('https://***.com/');
  const content = await page.property('content');
  console.log(content);

  await instance.exit();
)();

或者如果你只是想测试,你可以使用npx

npx phantom@latest https://***.com/

【讨论】:

是否允许在给定字符串的情况下呈现 HTML?【参考方案2】:

从你的 cmets 来看,我猜你有 2 个选择

    尝试找一个phantomjs节点模块-https://github.com/amir20/phantomjs-node 将 phantomjs 作为节点内的子进程运行 - http://nodejs.org/api/child_process.html

编辑:

似乎 phantomjs 建议子进程作为与节点交互的一种方式,请参阅常见问题解答 - http://code.google.com/p/phantomjs/wiki/FAQ

编辑:

用于获取页面 HTML 标记的示例 Phantomjs 脚本:

var page = require('webpage').create();  
page.open('http://www.google.com', function (status) 
    if (status !== 'success') 
        console.log('Unable to access network');
     else 
        var p = page.evaluate(function () 
            return document.getElementsByTagName('html')[0].innerHTML
        );
        console.log(p);
    
    phantom.exit();
);

【讨论】:

你能举个例子吗?抓取页面,运行 javascript,获取 html? 你可以简单地使用'page.content',不需要评估任何东西。 这很好,但是......在使用 node 包装的脚本中使用 require('webpage') 很困难,因为网页模块在 node 中未定义,它处于幻像中。有人有什么想法吗? “网页”是节点和幻象的通用模块吗?或者我只能在幻影上下文中使用 require 吗? @AdamWaite 评估是“沙盒”,无法执行要求。您必须将闭包中的所有内容传递给 evaluate()。 有没有人能够同时运行两个子进程进行 phantomjs 调用?【参考方案3】:

这是一个旧版本,我使用运行 node、express 和 phantomjs 将页面保存为 .png。您可以相当快地对其进行调整以获取 html。

https://github.com/wehrhaus/sitescrape.git

【讨论】:

仅供参考,如果您要使用链接来提供答案,最好包含足够的信息,以防万一链接在未来某个时间点断开,您的答案不会变得毫无用处。 保存为 png 你只需要 page.render('file.png')【参考方案4】:

为什么不直接使用呢?

var page = require('webpage').create();
page.open("http://example.com", function (status)

    if (status !== 'success') 
    
        console.log('FAIL to load the address');            
     
    else 
    
        console.log('Success in fetching the page');
        console.log(page.content);
    
    phantom.exit();
);

【讨论】:

【参考方案5】:

如果有人偶然发现这个问题,请延迟更新:

我的一位同事在 GitHub 上开发的一个项目正是旨在帮助您做到这一点:https://github.com/vmeurisse/phantomCrawl。

它还有些年轻,它肯定缺少一些文档,但提供的示例应该有助于进行基本的爬取。

【讨论】:

【参考方案6】:

我过去使用过两种不同的方法,包括查询 Declan 提到的 DOM 的 page.evaluate() 方法。我从网页传递信息的另一种方法是从那里将其吐出到 console.log(),并在 phantomjs 脚本中使用:

page.onConsoleMessage = function (msg, line, source) 
  console.log('console [' +source +':' +line +']> ' +msg);

我也可能会在 onConsoleMessage 中捕获变量 msg 并搜索一些封装数据。取决于你想如何使用输出。

然后在 Nodejs 脚本中,您必须扫描 Phantomjs 脚本的输出:

var yourfunc = function(...params...) 
  var phantom = spawn('phantomjs', [...args]);
  phantom.stdout.setEncoding('utf8');
  phantom.stdout.on('data', function(data) 
    //parse or echo data
    var str_phantom_output = data.toString();
    // The above will get triggered one or more times, so you'll need to
    // add code to parse for whatever info you're expecting from the browser
  );
  phantom.stderr.on('data', function(data) 
    // do something with error data
  );
  phantom.on('exit', function(code) 
    if (code !== 0) 
      // console.log('phantomjs exited with code ' +code);
     else 
      // clean exit: do something else such as a passed-in callback
    
  );

希望对一些人有所帮助。

【讨论】:

以上是关于使用 PhantomJS 和 node.js 保存和渲染网页的主要内容,如果未能解决你的问题,请参考以下文章

phantomjs 可以与 node.js 一起使用吗?

是否可以使用 PhantomJS 和 Node 从模板动态生成 PDF?

Node.js&co - 避免混合promises和事件回调

你没有安装'phantomjs'

Horseman —— Node.js 的网页浏览扩展

node.js 模块和其下载资源的镜像设置