执行页面的JavaScript后保存页面的HTML输出

50

我正在尝试爬取一个网站,该网站首先加载html/js,然后使用js修改表单输入字段并进行POST请求。如何获取POST页面的最终html输出?

我尝试使用phantomjs来实现,但似乎它只有渲染图像文件的选项。在网上搜索表明应该是可能的,但我无法弄清楚如何做到。我的尝试:

var page = require('webpage').create();
var fs = require('fs');
page.open('https://www.somesite.com/page.aspx', function () {
    page.evaluate(function(){

    });

    page.render('export.png');
    fs.write('1.html', page.content, 'w');
    phantom.exit();
});

这段代码将被用于给客户端使用,我不能指望他安装太多软件包(如Node.js、CasperJS等)。

谢谢


你必须使用Python吗?Java是一个选择吗? - OakNinja
您还可以使用 document.outerHTML 获取页面的内容。 - MIdhun Krishna
7个回答

27

你的输出代码是正确的,但存在同步性问题。你的输出行在页面加载完成前被执行。你可以使用onLoadFinished回调函数来确定何时发生这种情况。详见完整代码如下。

    var page = new WebPage()
    var fs = require('fs');

    page.onLoadFinished = function() {
      console.log("page load finished");
      page.render('export.png');
      fs.write('1.html', page.content, 'w');
      phantom.exit();
    };

    page.open("http://www.google.com", function() {
      page.evaluate(function() {
      });
    });

使用类似Google这样的网站时,它会非常快速地加载,以至于您经常可以像内联一样执行屏幕截图。在phantomjs中时间是一个棘手的问题,有时我使用setTimeout来测试时间是否成为了一个问题。


图片和样式怎么办? - Toolkit

4

当我直接复制您的代码并将URL更改为www.google.com时,它可以正常工作,并保存了两个文件:

  • 1.html
  • export.png

请注意,这些文件将被写入您运行脚本的位置,而不是您的.js文件所在的位置。


2

经过两天的挣扎和沮丧,我终于解决了类似的问题。关键是在PhantomJS官方网站中使用了waitfor.js例子。祝你开心!

"use strict";

function waitFor(testFx, onReady, timeOutMillis) {
    var maxtimeOutMillis = timeOutMillis ? timeOutMillis : 3000, //< Default Max Timout is 3s
        start = new Date().getTime(),
        condition = false,
        interval = setInterval(function() {
            if ( (new Date().getTime() - start < maxtimeOutMillis) && !condition ) {
                // If not time-out yet and condition not yet fulfilled
                condition = (typeof(testFx) === "string" ? eval(testFx) : testFx()); //< defensive code
            } else {
                if(!condition) {
                    // If condition still not fulfilled (timeout but condition is 'false')
                    console.log("'waitFor()' timeout");
                    phantom.exit(1);
                } else {
                    // Condition fulfilled (timeout and/or condition is 'true')
                    console.log("'waitFor()' finished in " + (new Date().getTime() - start) + "ms.");
                    typeof(onReady) === "string" ? eval(onReady) : onReady(); //< Do what it's supposed to do once the condition is fulfilled
                    clearInterval(interval); //< Stop this interval
                }
            }
        }, 250); //< repeat check every 250ms
};


var page = require('webpage').create();

// Open Twitter on 'sencha' profile and, onPageLoad, do...
page.open("http://twitter.com/#!/sencha", function (status) {
    // Check for page load success
    if (status !== "success") {
        console.log("Unable to access network");
    } else {
        // Wait for 'signin-dropdown' to be visible
        waitFor(function() {
            // Check in the page if a specific element is now visible
            return page.evaluate(function() {
                return $("#signin-dropdown").is(":visible");
            });
        }, function() {
           console.log("The sign-in dialog should be visible now.");
           phantom.exit();
        });
    }
});

0

我正在使用CasperJS来运行与PhantomJS相关的测试。我将以下代码添加到我的tearDown函数中:

var require = patchRequire(require);
var fs = require('fs');

casper.test.begin("My Test", {
    tearDown: function(){
        casper.capture("export.png");
        fs.write("1.html", casper.getHTML(undefined, true), 'w');
    },
    test: function(test){
        // test code

        casper.run(function(){
            test.done();
        });
    }
});

请查看capturegetHTML的文档。


0

我尝试了几种方法来完成类似的任务,最好的结果是使用Selenium。

在尝试PhantomJS和Cheerio之前。Phantom在执行页面上的JS时经常崩溃。


-2

除了使用一个无头浏览器来模拟ajax调用并对每个请求进行后处理外,我脑海中想到的一个方法是模拟ajax调用并逐步集成网页。然而,这种方法通常比较棘手,应该作为最后的选择,除非你真的喜欢深入研究javascript代码。


-10

这可以很容易地通过一些 PHP 代码和 JavaScript 来完成 使用 fopen() 和 fwrite() 并使用以下函数来保存它: var generatedSource = new XMLSerializer().serializeToString(document);


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接