【问题标题】:Saving interactive graphs through viewer (export) as (PNG)通过查看器(导出)将交互式图形保存为 (PNG)
【发布时间】:2017-11-08 11:25:44
【问题描述】:

我想将我的交互式图表保存为 png,我可以通过查看器将其导出为 png,但我有成千上万个,必须自动获取它们。

有一种方法是使用webshot 包,但我尝试了这种方法,它需要很多时间,因为我想同时保存它们,例如:我有 4000 个使用 R 生成的 html 图形和必须以 1 分钟的时间间隔将它们保存为图像,当我使用 webshot 时,大约需要 43 分钟,因为 system2 需要很多时间。

所以我想使用查看器窗格使用的功能导出它们,这里有一张图片说明我想要什么。

这里的代码作为交互式图形的示例,这并不意味着我的图形 r 传单类,我提供它作为示例。

library(leaflet)

m <- leaflet() %>%
  addTiles() %>%  # Add default OpenStreetMap map tiles
  addMarkers(lng=174.768, lat=-36.852, popup="The birthplace of R")

这就是我的想法:

function(m,"SaveAs.png")

我需要帮助,我搜索了很多并花了很多时间试图找到解决方案。


根据这个问题 How to save Leaflet in R map as png or jpg file?

它与我的问题不同,我需要任何交互式图表的通用函数,plotly 的函数但它仅适用于情节图,还有使用 PhantomJs 的问题使用 webshot 函数,我在上面提到 PhantomJS 也太慢了Selenium 也是 wkhtmltoimage,我尝试了很多东西。

请注意我需要通用函数或至少 viewer 正在使用的函数

【问题讨论】:

  • 除了方便之外,时间限制的原因是什么?
  • 真实的流数据,并进行比较,如果超过1分钟,则比较错误
  • @herbaman,不,不是,他们使用 webshot 和 mapshot,他们都使用 phantomJS,我以传单代码为例。
  • 您使用什么小部件?对你正在做的事情保持腼腆并不会鼓励人们帮助你。根据您使用的小部件,可能/可能有符合您要求的非交互式绘图。

标签: r


【解决方案1】:

捕获 htmlwidgets 位图(如传单)的唯一方法是将它们加载到浏览器上下文中,捕获视口的一部分(或全部)并将其写入文件。这是重量级浏览器上下文中一个丑陋的往返过程,将内部 DOM 表示之间的数据编组到 HAR(在幕后)——将二进制位编码为 base64,到浏览器上下文代理/驱动程序,到 R,它们从 base64 到内存或文件。

还有一个额外的问题是,许多保存到文件的 HTML 小部件并不总是在静态文件上下文中加载(即您需要一个正在运行的 Web 服务器)。我不知道这是否适用于 googleway 保存的小部件,但它通常适用于传单。

对于以下内容,您需要:

  • 了解如何安装 devd 二进制文件
  • 了解如何使用 chrome 驱动程序安装 selenium(safari 驱动程序可能会更快,因为它的 js 引擎更快)
  • 使用 Chrome 驱动程序启动 selenium

玩具示例设置以节省 5 个小部件:

library(seleniumPipes)
library(leaflet)
library(purrr)
library(devd) # install_github("hrbrmstr/devd")

m <- leaflet() %>%
  addTiles() %>%
  addMarkers(lng=174.768, lat=-36.852, popup="The birthplace of R")

dir.create("/tmp/pages", showWarnings = FALSE)
dir.create("/tmp/pngs", showWarnings = FALSE)

walk(1:5, ~saveWidget(m, file.path("/tmp/pages", sprintf("%x.html", .x))))

启动一个 selenium 会话并启动一个 Web 服务器:

remDr <- remoteDr(browserName = "chrome", port = 4444L)

proc <- devd_start("/tmp/pages", open_browser = FALSE)

浏览文件并截取屏幕截图:

list.files("/tmp/pages", "*.html$", full.names = FALSE) %>% 
  walk(~{
    print(system.time({
      page_url <- sprintf("http://devd.io:8000/%s", .x)
      out_file <- sprintf("/tmp/pngs/%s.png", .x)
      remDr %>% 
        go(page_url) %>% 
        takeScreenshot(file=out_file)
    }))
  })

你得到:

##  user  system elapsed 
## 0.473   0.082   6.561 
## 0.449   0.083   4.110 
## 0.447   0.073   4.429 
## 0.419   0.068   3.568 
## 0.423   0.085   4.493 

对于那个序列。

如果我们尝试仅捕获 png 并关闭一些 takeScreenshot() 功能,也不会变得更好:

list.files("/tmp/pages", "*.html$", full.names = FALSE) %>% 
  map(~{
    print(system.time({
      page_url <- sprintf("http://devd.io:8000/%s", .x)
      out_file <- sprintf("/tmp/pngs/%s.png", .x)
      remDr %>% 
        go(page_url) %>% 
        takeScreenshot(display=FALSE, useViewer=FALSE, returnPNG=TRUE)
    }))
  }) -> pngs

##  user  system elapsed 
## 0.448   0.060   4.801 
## 0.440   0.058   4.894 
## 0.463   0.074   4.857 
## 0.466   0.068   5.010 

别忘了给网络服务器置顶:

devd_stop(proc)

可以通过并行处理来加快这一进程,但其他人比我更愿意为您提供免费咨询,特别是因为您没有而且仍然没有完全回答您的问题详细信息。答案主要是针对有类似需求但权利较少的其他人。

【讨论】:

  • 我也很确定(但没有时间检查法律术语)您故意违反了谷歌的服务条款,但由于缺乏问题透明度而无法确定.
  • 非常感谢,非常感谢您的帮助,但这需要很多时间,webshot 大约需要 4 秒,如果我输入超过 1 个 url,每个 html 大约需要 2 秒。
  • 据此违反了 googel 的条款。我没有,我有隐私,我不能分享我的代码,而且你总是想知道更多不属于问题的信息,所以请不要再说了。
  • 我会根据提供的信息推断我推断出的内容。您也可以直接在 javascript 中编写 phantomjs 脚本。 IMO 您为您的工作流程选择了糟糕的选择,没有预先满足足够的性能要求,并且在后端缺乏彻底性并要求社区救助您。这听起来像是一个业务流程,因此从长远来看,您可能必须实际花钱请人来帮助您。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-11-29
  • 2021-04-21
相关资源
最近更新 更多