简体   繁体   English

如何在PhantomJS中用远程JavaScript替换DOM节点

[英]How to replace DOM node with remote javascript in PhantomJS

I'm new to PhantomJS and javascript, so forgive me if there is a simple solution. 我是PhantomJS和javascript的新手,如果有一个简单的解决方案,请原谅我。

I'm using PhantomJS to do screenshots of websites, and I want to replace certain DOM nodes with dynamic content from a remote javascript, something like this: 我正在使用PhantomJS制作网站的屏幕截图,并且想用远程javascript中的动态内容替换某些DOM节点,如下所示:

<script language="JavaScript" src="http://server/dynamic.js" type="text/javascript"></script>

My first try: 我的第一次尝试:

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

page.open('http://stackoverflow.com', function (status) {
    if (status !== 'success') {
        phantom.exit();
    }

    page.evaluate(function() {

        //// Case #1: what I really want
        // var s = '<script language="JavaScript" src="http://server/dynamic.js" type="text/javascript"></script>';

        //// Case #2: simple js test case
        // var s = '<script language="JavaScript" type="text/javascript">document.write("<p>THIS IS A TEST</p>");</script>';

        //// Case #3: very simple case
        var s = '<b>THIS IS A TEST</b>';

        var node = document.getElementById('mainbar');
        var pnode = node.parentNode;

        var newele = document.createElement('div');
        newele.innerHTML = s;

        pnode.replaceChild(newele, node);
    });

    page.render('test.jpg');

    phantom.exit();
});

For the simple case (case #3) where I'm just replacing it with some text, it works fine, but not for either of the javascript cases. 对于简单的情况(第3种情况),我只是将其替换为一些文本,它可以正常工作,但不适用于两种javascript情况。 It seems the javascript isn't being evaluated after being inserted via replaceChild(). 似乎通过replaceChild()插入后,没有对javascript进行评估。 I tried page.reload() just before page.render() but it didn't help. 我在page.render()之前尝试过page.reload(),但没有帮助。

Next, I tried creating the new element using iframe: 接下来,我尝试使用iframe创建新元素:

var newele = document.createElement('iframe');
newele.setAttribute('src', 'javascript:document.write("<p>THIS IS A TEST</p>");');

This works for the simple js test case #2, but I can't figure out how to make iframe work with what I really want (Case #1). 这适用于简单的js测试用例#2,但是我不知道如何使iframe满足我的实际需求(用例#1)。

Any suggestions? 有什么建议么?

I came up with a workable solution: 我想出了一个可行的解决方案:

var newele = document.createElement('iframe');
newele.setAttribute('src', 'javascript:document.write("<script src=\'http://server/dynamic.js\'></script>");');

I also had to put in a bit of delay: 我还不得不拖延一点:

window.setTimeout(function () {
    page.render('test.jpg');
    phantom.exit();
}, 500);

This works, but feels a little klugy to me. 这行得通,但让我感到有些困惑。 I would love to hear a better solution. 我希望听到更好的解决方案。

Nope, you can add your javascript reference to the page like this, right before calling evaluate the first time (excerpt): 不会,您可以在第一次调用评估之前(摘录)将您的javascript引用添加到该页面,如下所示:

...
        page.open(url, function (status) {
            if (status !== 'success') {
                console.log('Error: Cannot load url. Status: {0}.'.format(status));
                phantom.exit(1);
            } else {
                page.injectJs('../../../code/common/jquery.min.js');
                // call evaluate once to change the dropdown:
                page.evaluate(function (myobj) {
                        // manipulate DOM here with jquery, or whatever you want.
                }, myobj);
...

Please note that you can call evaluate several times, so you can extract stuff from the page, call javascript functions from the page, modify DOM, etc. 请注意,您可以多次调用评估,因此您可以从页面中提取内容,从页面中调用javascript函数,修改DOM等。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM