phantomjs - page.evaluate 更新后无法正确呈现页面; Page#content 正确显示
phantomjs - page.evaluate not rendering page properly after update; Page#content displaying correctly
几天来我一直在摸索这段代码,在经历了许多挑战之后,我几乎得到了我想要的结果。该代码假设使用默认值(速度计针)100 呈现类似速度计的仪表(见下文)。我正在尝试使用 Javascript(通过 PhantomJS/automation)删除 HTML 标签中的 DOM 并将其替换为更新后的内容。 内容相同,只是值需要从 100 更改为其他内容。
经过大量阅读(我的背景是 Ruby),我正在正确地做这件事,并且我已经成功地用我想要的确切 HTML 更新了 DOM,然而,使用 PhantomJS 渲染更新后的图像 DOM 只会得到部分完整的图像。
我注意到有相当多的 Whosebug 线程关于允许页面完全呈现 (setTimeout),但是当我添加超时时(见下面的代码)它被忽略并且代码执行不到第二.
有人可以帮助我以正确的方式实现这个超时吗?我认为这是问题所在,因为执行 Page#evaluate
后 Page#content
的结果是正确的,并且结果 HTML 在独立打开时完美呈现。
代码:
// Open chart.html from the local filesystem
page.open('file:///c:/temp/chart.html', function(status) {
setTimeout(function() {
page.evaluate(function() {
// Remove the HTML script tag with an ID of 'removeMe' from the DOM
var elem = document.getElementById('removeMe');
document.getElementById('removeMe').parentNode.removeChild(elem);
// Create a new script tag and populate it with the appropriate content
var s = document.createElement('script');
s.type = 'text/javascript';
// Per user request, including the full scriptContent var (originally omitted for brevity)
var scriptContent = 'AmCharts.makeChart("chartdiv", { "type": "gauge", "marginBottom": 20, "marginTop": 40, "startDuration": 0, "fontSize": 13, "theme": "dark", "arrows": [ { "id": "GaugeArrow-1", "value": 30 } ], "axes": [ { "axisThickness": 1, "bottomText": "0 km/h", "bottomTextYOffset": -20, "endValue": 220, "id": "GaugeAxis-1", "valueInterval": 10, "bands": [ { "alpha": 0.7, "color": "#00CC00", "endValue": 90, "id": "GaugeBand-1", "startValue": 0 }, { "alpha": 0.7, "color": "#ffac29", "endValue": 130, "id": "GaugeBand-2", "startValue": 90 }, { "alpha": 0.7, "color": "#ea3838", "endValue": 220, "id": "GaugeBand-3", "innerRadius": "95%", "startValue": 130 } ] } ], "allLabels": [], "balloon": {}, "titles": [] } );';
// suggested elsewhere on SO; for all browser compatibility
try {
s.appendChild(document.createTextNode(scriptContent));
document.head.appendChild(s);
} catch (e) {
s.text = scriptContent;
document.head.appendChild(s);
}
});
}, 5000);
// RENDER THE NEW IMAGE; this is rendering the same image but needle is missing entirely
page.render('after_change.png');
phantom.exit();
});
期望的结果
上面的scriptContent
变量包含脚本标签的更新内容;它正确地将针值更新为 75,但 after_change.png
缺少针。我需要指针显示在 75。
HTML
<script type="text/javascript" src="https://www.amcharts.com/lib/3/amcharts.js"></script>
<script type="text/javascript" src="https:http://cdn.amcharts.com/lib/3/gauge.js"></script>
<script type="text/javascript" src="https://www.amcharts.com/lib/3/themes/dark.js"></script>
<script type="text/javascript" id="removeMe">
...
// these contents should be completely replaced; no other relevant HTML
...
</script>
<body>
<div id="chartdiv" ></div>
</body>
参考Material
这是我正在使用的准确仪表 -- amCharts Gauge 的 100% 默认设置:
https://live.amcharts.com/zkyZm/edit/
让我们按以下顺序考虑此任务的连续操作:
- 打开页面。
- 对其进行调整
- 截图
因此,如果您必须等待某事,它可能正在制作屏幕截图。
因此,让我们用伪代码重写您的脚本:
// 1. Open the page
page.open('file:///c:/temp/chart.html', function(status) {
// 2. Make adjustments
page.evaluate(function() {
/// Do stuff
});
// 3. Make screenshot, but not before waiting 5 seconds
// for browser to catch up with step 2.
setTimeout(function(){
page.render('after_change.png');
phantom.exit();
}, 5000);
});
几天来我一直在摸索这段代码,在经历了许多挑战之后,我几乎得到了我想要的结果。该代码假设使用默认值(速度计针)100 呈现类似速度计的仪表(见下文)。我正在尝试使用 Javascript(通过 PhantomJS/automation)删除 HTML 标签中的 DOM 并将其替换为更新后的内容。 内容相同,只是值需要从 100 更改为其他内容。
经过大量阅读(我的背景是 Ruby),我正在正确地做这件事,并且我已经成功地用我想要的确切 HTML 更新了 DOM,然而,使用 PhantomJS 渲染更新后的图像 DOM 只会得到部分完整的图像。
我注意到有相当多的 Whosebug 线程关于允许页面完全呈现 (setTimeout),但是当我添加超时时(见下面的代码)它被忽略并且代码执行不到第二.
有人可以帮助我以正确的方式实现这个超时吗?我认为这是问题所在,因为执行 Page#evaluate
后 Page#content
的结果是正确的,并且结果 HTML 在独立打开时完美呈现。
代码:
// Open chart.html from the local filesystem
page.open('file:///c:/temp/chart.html', function(status) {
setTimeout(function() {
page.evaluate(function() {
// Remove the HTML script tag with an ID of 'removeMe' from the DOM
var elem = document.getElementById('removeMe');
document.getElementById('removeMe').parentNode.removeChild(elem);
// Create a new script tag and populate it with the appropriate content
var s = document.createElement('script');
s.type = 'text/javascript';
// Per user request, including the full scriptContent var (originally omitted for brevity)
var scriptContent = 'AmCharts.makeChart("chartdiv", { "type": "gauge", "marginBottom": 20, "marginTop": 40, "startDuration": 0, "fontSize": 13, "theme": "dark", "arrows": [ { "id": "GaugeArrow-1", "value": 30 } ], "axes": [ { "axisThickness": 1, "bottomText": "0 km/h", "bottomTextYOffset": -20, "endValue": 220, "id": "GaugeAxis-1", "valueInterval": 10, "bands": [ { "alpha": 0.7, "color": "#00CC00", "endValue": 90, "id": "GaugeBand-1", "startValue": 0 }, { "alpha": 0.7, "color": "#ffac29", "endValue": 130, "id": "GaugeBand-2", "startValue": 90 }, { "alpha": 0.7, "color": "#ea3838", "endValue": 220, "id": "GaugeBand-3", "innerRadius": "95%", "startValue": 130 } ] } ], "allLabels": [], "balloon": {}, "titles": [] } );';
// suggested elsewhere on SO; for all browser compatibility
try {
s.appendChild(document.createTextNode(scriptContent));
document.head.appendChild(s);
} catch (e) {
s.text = scriptContent;
document.head.appendChild(s);
}
});
}, 5000);
// RENDER THE NEW IMAGE; this is rendering the same image but needle is missing entirely
page.render('after_change.png');
phantom.exit();
});
期望的结果
上面的scriptContent
变量包含脚本标签的更新内容;它正确地将针值更新为 75,但 after_change.png
缺少针。我需要指针显示在 75。
HTML
<script type="text/javascript" src="https://www.amcharts.com/lib/3/amcharts.js"></script>
<script type="text/javascript" src="https:http://cdn.amcharts.com/lib/3/gauge.js"></script>
<script type="text/javascript" src="https://www.amcharts.com/lib/3/themes/dark.js"></script>
<script type="text/javascript" id="removeMe">
...
// these contents should be completely replaced; no other relevant HTML
...
</script>
<body>
<div id="chartdiv" ></div>
</body>
参考Material
这是我正在使用的准确仪表 -- amCharts Gauge 的 100% 默认设置: https://live.amcharts.com/zkyZm/edit/
让我们按以下顺序考虑此任务的连续操作:
- 打开页面。
- 对其进行调整
- 截图
因此,如果您必须等待某事,它可能正在制作屏幕截图。
因此,让我们用伪代码重写您的脚本:
// 1. Open the page
page.open('file:///c:/temp/chart.html', function(status) {
// 2. Make adjustments
page.evaluate(function() {
/// Do stuff
});
// 3. Make screenshot, but not before waiting 5 seconds
// for browser to catch up with step 2.
setTimeout(function(){
page.render('after_change.png');
phantom.exit();
}, 5000);
});