- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
我想在服务器端将一些定制的 CSS3/Javascript 动画序列渲染为一组 PNG 文件,然后将它们加入到单个视频文件中。
我看到了here PhantomJS 可以实现这一点。由于我对 Selenium 没有很大的背景,所以我不知道如何使其与 Selenium 相适应。我唯一知道的是如何make a single screenshot含 Selenium :
driver = webdriver.Chrome()
driver.get('mywebpage.com')
driver.save_screenshot('out.png')
driver.quit()
但它只执行单个屏幕截图。
请教如何通过 Selenium/Python 截取 CSS/Javascript 动画从头到尾的一组屏幕截图。
PS:我在 Vagrant VM 上使用 Python 3.5 和 chrome 作为 selenium webdriver
提前非常感谢
最佳答案
编辑4:
正如 @Arakis 指出的,如果不接管浏览器中的动画,您想要的东西(任何给定动画的足够的屏幕截图值得制作视频)是不可能的。如果您无法接管动画,这是您可以获得的最好的:
import os
import time
from selenium import webdriver
from selenium.webdriver.chrome.options import Options
TARGET_FOLDER = r'C:\test\animated_you_not_wanted\{}.png'
WINDOW_SIZE = 1920, 1080
options = Options()
options.add_argument("--headless")
options.add_argument("--no-sandbox")
options.add_argument("start-maximized")
options.add_argument("disable-infobars")
options.add_argument("--disable-extensions")
shots = []
if not os.path.isdir(os.path.dirname(TARGET_FOLDER)):
os.makedirs(os.path.dirname(TARGET_FOLDER))
driver = webdriver.Chrome(executable_path=r'c:\_\chromedriver.exe', options=options,
service_args=['--ignore-ssl-errors=true', '--ssl-protocol=any'])
# driver = webdriver.Chrome(executable_path=r'c:\_\chromedriver.exe')
driver.set_window_size(*WINDOW_SIZE)
driver.get('https://daneden.github.io/animate.css/')
# we know that the animation duration on this page is 1 sec so we will try to record as many frames as possible in 1 sec
start_time = time.time()
while time.time() <= start_time + 1:
shots.append(driver.get_screenshot_as_png())
# dumping all captured frames
for i in range(len(shots)):
with open(TARGET_FOLDER.format(i), "wb") as f:
f.write(shots[i])
如果您运行上面的代码,您将获得大约 3 个屏幕截图,如果您有一台野兽机器,则可能获得 4 个屏幕截图。
为什么会发生这种情况?当selenium抓取屏幕截图时,浏览器中的动画不会停止并思考是否可以继续前进,它只是像平常一样独立运行。 Selenium 在此分辨率 (1920x1080) 下能够在一秒钟内抓取 3-4 个屏幕截图。如果将屏幕分辨率降低到 640x480,根据您的机器,您每秒将获得 5-7 个屏幕截图,但该帧速率仍然与您可能想要的相差非常非常远。 Selenium 通过 API 与浏览器交互,但不控制浏览器。截屏需要时间,当 selenium 将渲染的页面作为图像抓取时,动画会继续。
如果您想要具有高帧速率的流畅动画,您必须通过覆盖动画状态来控制动画。你必须:
animation-play-state
设置为暂停
animation-duration
设置为合理的长度animation-delay
设置为负值以选择给定的动画状态for
循环中调整animation-delay
并抓取屏幕截图在给定页面 ( https://daneden.github.io/animate.css/ ) 的打开动画中,有 2 个使用相同动画进行动画处理的 Web 元素。因此,下面的代码所做的就是上面的列表,但有一点额外的内容:它“步进”两个元素的动画周期。
import os
import time
from selenium import webdriver
from selenium.webdriver.chrome.options import Options
TARGET_FOLDER = r'C:\test\animated_you_wanted\{}.png'
WINDOW_SIZE = 1920, 1080
ANIM_DURATION = 2
FRAMES = 60
BASE_SCR = 'arguments[0].setAttribute("style", "display: block;animation-delay: {}s;animation-duration: {}s; animation-iteration-count: infinite;animation-play-state: paused;")'
options = Options()
options.add_argument("--headless")
options.add_argument("--no-sandbox")
options.add_argument("start-maximized")
options.add_argument("disable-infobars")
options.add_argument("--disable-extensions")
driver = webdriver.Chrome(executable_path=r'c:\_\chromedriver.exe', options=options,
service_args=['--ignore-ssl-errors=true', '--ssl-protocol=any'])
# driver = webdriver.Chrome(executable_path=r'c:\_\chromedriver.exe')
driver.set_window_size(*WINDOW_SIZE)
driver.get('https://daneden.github.io/animate.css/')
header = driver.find_element_by_xpath('//*[@class="site__header island"]')
content = driver.find_element_by_xpath('//*[@class="site__content island"]')
shots = []
for frame in range(FRAMES):
for elem in (header, content):
driver.execute_script(BASE_SCR.format((frame / FRAMES) * -ANIM_DURATION, ANIM_DURATION), elem)
shots.append(driver.get_screenshot_as_png())
if not os.path.isdir(os.path.dirname(TARGET_FOLDER)):
os.makedirs(os.path.dirname(TARGET_FOLDER))
# dumping all captured frames
for i in range(len(shots)):
with open(TARGET_FOLDER.format(i), "wb") as f:
f.write(shots[i])
这是使用 Selenium 可以获得的最好结果。
奖金:(或编辑5?)
我想知道是否真的不可能使用完全通用的解决方案(独立于网页)每秒挤出超过 5-6 帧。我在想这个:
所以我决定:
这是代码,比 python 包含更多 JS :D :
import base64
import os
import time
from selenium import webdriver
from selenium.webdriver.chrome.options import Options
TARGET_FOLDER = r'C:\test\animated_you_actually_wanted\{}.png'
WINDOW_SIZE = 800, 600
ANIM_DURATION = 1
FRAMES = 15
BASE_SCR = """
function load_script(){
let ss = document.createElement("script");
ss.src = "https://cdnjs.cloudflare.com/ajax/libs/html2canvas/0.4.1/html2canvas.js";
ss.type = "text/javascript";
document.getElementsByTagName("head")[0].appendChild(ss);
};
load_script();
shots = [];
window.take = function() {
html2canvas(document.body, {
onrendered: function (canvas) {
shots.push(canvas);
}
})
};
window.record = function(times, sleep){
for (let i=0; i<times; i++){
setTimeout(window.take(), sleep*i)
console.log("issued screenshot with sleep: " + sleep*i)
}
};
""" + """
document.body.setAttribute("style", "width: {width}px; height: {height}px");
""".format(width=WINDOW_SIZE[1], height=WINDOW_SIZE[0])
RECORD_SCR = """
document.body.innerHTML = document.body.innerHTML
window.record({}, {})
"""
GRAB_SCR = """
function getShots(){
let retval = []
for (let i=0; i<shots.length; i++){
retval.push(shots[i].toDataURL("image/png"))
}
return retval;
}
return getShots()
"""
options = Options()
options.add_argument("--headless")
options.add_argument("--no-sandbox")
options.add_argument("start-maximized")
options.add_argument("disable-infobars")
options.add_argument("--disable-extensions")
if not os.path.isdir(os.path.dirname(TARGET_FOLDER)):
os.makedirs(os.path.dirname(TARGET_FOLDER))
driver = webdriver.Chrome(executable_path=r'c:\_\chromedriver.exe', options=options,
service_args=['--ignore-ssl-errors=true', '--ssl-protocol=any'])
# driver = webdriver.Chrome(executable_path=r'c:\_\chromedriver.exe')
driver.set_window_size(*WINDOW_SIZE)
driver.get('https://daneden.github.io/animate.css/')
driver.execute_script(BASE_SCR)
time.sleep(3)
driver.execute_script(RECORD_SCR.format(FRAMES, (ANIM_DURATION/FRAMES)*100))
shots = []
while len(shots) < FRAMES:
shots = driver.execute_script(GRAB_SCR)
# dumping all captured frames
for i in range(len(shots)):
with open(TARGET_FOLDER.format(i), "wb") as f:
f.write(base64.urlsafe_b64decode(shots[i].split('base64,')[1]))
driver.quit()
html2canvas 实验的结果:
关于javascript - 使用 Python 使用 Selenium 将 CSS/Javascript 动画渲染为一系列图像文件,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/52753412/
我有一个名为 main.css 的 css 文件和另一个名为 style.css 的文件。我怎样才能在 main.css 中做到这一点? .someClass { //apply rules to
在更新我的 css 之前,我在 Login.css 中有以下内容: body { background-image: url('./pictures/fond.png'); bac
我的 share point 2013 核心 css 和我的 css 之间存在 css 冲突。所以我想把我所有的类都放在 div #s4-workspace 下但是我搜索了一种方法来将所有类分组到这个
我知道您可以覆盖 jsp 页面从 jsp 包含 CSS 文件(即全局 CSS 文件)继承的 CSS 属性。 但是,如果元素中的某个属性弄乱了特定页面,而我不想只使用内联 CSS 在该页面中使用它怎么办
我刚刚发现了 initial-scale 元属性。 以前,我一直在使用 default.css 来定义我所有的样式和大小(用于字体和元素),以便它们在桌面计算机的屏幕上显示得很好。然后,如果您使用的是
我正在尝试使用 LESS CSS 来编写我的 CSS。我已经按顺序导入了 style.less 和 less.js 文件。 现在我想提取 LESS 生成的 CSS。有什么办法可以做到吗?我不想使用脚本
我想知道是否有任何一种软件可以读取大量内联样式中的 HTML 文档并将所有这些样式转换为外部 css 文件。如果只有一页,我可以手动完成。但是有100页。有人有想法吗? 最佳答案 就像有人说的那样,“
当我想从 Styled Components 迁移到 CSS Modules 时,出现了以下问题。 假设我有以下样式组件,它接受动态参数 offset和一个动态 CSS 字符串 theme : con
有没有办法将 CSS 类定义为与另一个类相等?例如,如果我有一个类: .myClass{ background-color: blue; } 有没有一种方法可以将第二个类定义为与 myClas
我正在尝试制作一组按钮,这些按钮贴在页面底部并且由固定的空间隔开。我正在使用 angularJS 的 ng-repeat 指令通过 ajax 请求获取数据,然后我用它来显示按钮。 我的问题在于让按
浏览器是否在加载 CSS 文件时解析 CSS?还是在整个 CSS 文件被浏览器下载后才进行解析?不同浏览器的做法有区别吗?我在哪里可以找到这种底层信息? 这个问题不是 Load and executi
这个问题在这里已经有了答案: Can a CSS class inherit one or more other classes? (29 个答案) 关闭 3 年前。 标题有点乱,我给大家看一下。假
我遇到了最奇怪的问题...... 在最简单的形式中,我有一个包含以下内容的 index.html 文件: (在尝试确定根本原因的过程中,我已经大大减少了它) 当我查看页面的源代码时,我得到以下信息:
我正在使用 Mindscape Workbench 来最小化我的 scss 文件。我的页面设置为使用 *.min.css 文件。在随机时间,min 文件不会与系统的其余部分一起发布。 我有很多 css
请告诉我 CSS 框架和 CSS 网格之间的区别。 最佳答案 CSS 框架也可以是 CSS 网格框架。 CSS 网格框架用于构建 CSS 布局。有一些框架除了构建布局还有其他用途,例如 Hartija
我有无法从页面中删除或更改的 original.css 文件。原始.css table { border-collapse: collapse; border-spacing: 0;
我以前使用 bootstrap css import 很好。 但是我正在尝试使用 CSS 模块,所以我添加了几行。 { test: /\.css$/, use:
有没有办法在 css 选择器中创建一个 css 组。 例如: .SectionHeader { include: .foo; include: .bar; include: .
今天我学习了 CSS 中的两个概念,一个是 CSS 定位(静态、相对、绝对、固定),另一个是 CSS Margin,它定义了元素之间的空间。 假设我想移动一个元素,这是最好的方法吗?因为这两个概念似乎
var paths = { css: './public/apps/user/**/*.css' } var dest = { css: './public/apps/user/css/' } /
我是一名优秀的程序员,十分优秀!