PhantomJS无法加载Google地图。

11

我的最终目标是使用嵌入了JavaScript的本地HTML文件创建一个带有多边形的地图,并使用PhantomJS对其进行截屏。我已经编写了一个简单的JS文件来实现这个目标:

var page = require('webpage').create();
page.open('https://www.google.com/maps', function(status) {
  console.log('State: ' + status);
  if(status === 'success') {
      page.render('example.pdf', {format: 'pdf', quality: '100'});
  }
  phantom.exit();
}); 

这会返回错误信息:
ReferenceError: Can't find variable: google

我已经在本地HTML文件和其他使用谷歌地图的网站上尝试过这个方法,但是一直出现相同的错误。 我成功地截取了其他没有谷歌地图的网站的屏幕截图。 在互联网上搜索,似乎没有人遇到过像这样的问题,并且已成功地截取了带有谷歌地图的页面...所以我想知道可能出了什么问题。
另一个注意点:我将PhantomJS作为gem安装在我的rails项目中,并使用此gem通过rails控制台运行javascript文件。 我已尝试使用PhantomJS的标准安装(v2.0.0),但仍然无法正常工作。

6
尝试运行带有--ignore-ssl-errors=true命令行选项的程序。 - Artjom B.
我可以使用 phantomjs script.js 正常运行您的示例代码。但需要考虑一件事情:Google 地图瓦片(或矢量数据)是自己异步加载的,您可能需要在内部的 page.open 块周围添加一个等待时间为几秒钟的 window.setTimeout,以便在页面完全加载时将其呈现为 PDF。否则,您的 PDF 将为空白/灰色。 - chrki
@ArtjomB的解决方案对我没用 :( - JustGage
以上代码片段对我来说运行良好!我正在运行phantomJS的2.1.1版本。 - hkasera
2个回答

1
你需要等待DOM中的元素。 例如在maps.google.com上,你可以等待水印加载完成,因为它是在所有瓦片加载完成后加载的。
var page = require('webpage').create();
page.open('https://www.google.com/maps', function (status) {
    console.log('State: ' + status);
    if (status === 'success') {
        waitFor(function () {
            return page.evaluate(function () {
                var document_contains_watermark =
                    document.body.contains(document.getElementById('watermark'));
                return document_contains_watermark;
            });
        }, function () {
            page.render('maps-google-com.pdf', {format: 'pdf', quality: '100'});
            phantom.exit();
        });
    }
});

function waitFor(testFn, onReady) {
    var loaded = false;
    var interval = setInterval(function () {
        loaded = testFn();
        if (loaded) {
            onReady();
            clearInterval(interval);
        }
    }, 1000);
}

如果您想在开发的页面上截屏,请使用相同的逻辑,但在谷歌地图空闲事件中自己添加一个元素。
google.maps.event.addListenerOnce(map, 'idle', function () {
    var loadedElem = document.createElement('div');
    loadedElem.setAttribute("id", "idLoadedElem");
    document.body.appendChild(loadedElem);
});

-1
你应该尝试一下puppeter,它会让这变得很容易:
const puppeteer = require('puppeteer');
(async () => {
  const browser = await puppeteer.launch();
  const page = await browser.newPage();
  await page.goto('https://example.com');
  await page.screenshot({path: 'example.pdf'});

  await browser.close();
})();

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