我正在抓一个网站,网页上播放了音频,我想知道音频什么时候播放完毕,所以我在音频webElement上添加了一个事件监听器来监听' onEnded'要触发的事件,我想从driver.execute_async_script中的callback()函数中注意到。
但我总是得到错误
TypeError: <function MissionContentItemHelper.audio_play_end at 0x10f3b7b70> is not JSON serializable.
我的问题是:
1.does arguments [arguments.length - 1]是指self.audio_play_end?
2.为什么错误输出是关于&#39; MissionContentItemHelper.audio_play_end不是JSON可序列化的&#39;?我无法在MissionContentItemHelper.audio_play_end和JSON之间看到任何线索。
3.调用audio_play_end的方式是否正确?
class MissionContentItemHelper:
def sleep(self):
audio = self.browser.find_element_by_css_selector('#audio')
self.browser.execute_async_script("""
var audio = arguments[0];
callback = arguments[arguments.length - 1];
audio.addEventListener("ended", function(_event) {
callback();
}
""", audio, self.audio_play_end)
@staticmethod
def audio_play_end():
print('the audio finished playing...')
答案 0 :(得分:0)
execute_async_script
的名字让很多人感到困惑。它不会从测试代码异步执行脚本,它只允许您执行从浏览器的主线程异步运行的脚本,如AJAX调用和JavaScript setTimeout
。
这些JavaScript函数和类似函数本身几乎立即返回,但它们采用在异步操作完成时执行的(JavaScript)函数参数。 execute_async_script
的作用与execute_script
完全相同,但它不是在函数本身返回时(几乎是立即返回)返回,而是提供自己的回调JavaScript函数(它作为最后一个参数传递,即&#39} ;为什么需要arguments[arguments.length - 1]
,你可以在你传递给execute_async_script
的JavaScript代码中使用它,将它作为回调传递给异步函数。 execute_async_script
仅在调用此回调时返回,而不是立即返回。
例如,在以下代码中,对execute_async_script
的调用就像延迟2秒:
browser.execute_async_script("setTimeout(arguments[0], 2000)")
请注意,因为我没有向脚本传递任何其他参数,所以arguments[0]
实际上是最后一个参数。
在您的情况下,您不必通过self.audio_play_end
,但您必须在JavaScript代码段内调用audio.play()
才能启动音频。 execute_async_script
只应在音频播放结束时返回。