如何从python中调用selenium execute_async_script中的回调函数

时间:2018-04-18 01:46:13

标签: python selenium scrapy

我正在抓一个网站,网页上播放了音频,我想知道音频什么时候播放完毕,所以我在音频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...')

1 个答案:

答案 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只应在音频播放结束时返回。