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

w6mmgewl  于 2023-01-30  发布在  Python
关注(0)|答案(3)|浏览(220)

我正在抓取一个网站,网页上正在播放音频,我想知道音频何时会播放完,所以我向音频webElement添加了事件侦听器,以监视"onEnded"事件是否触发,我想从driver. execute_async_script内的callback()函数中得到通知。
但我总是得到错误
TypeError: <function MissionContentItemHelper.audio_play_end at 0x10f3b7b70> is not JSON serializable.
我的问题是:
1.参数[参数.长度-1]是否引用www.example.com_play_end? self.audio _play_end ?
2.为什么错误输出是关于"www.example.com_play_end is not JSON serializable"?我看不出MissionContentItemHelper.audio_play_end和JSON之间有任何线索。 MissionContentItemHelper.audio _play_end is not JSON serializable'? i can't see any clue between MissionContentItemHelper.audio_play_end and JSON.
3.is the way calling audio_play_end correct?

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...')
5lwkijsr

5lwkijsr1#

execute_async_script的名字让很多人感到困惑,它并不与你的测试代码异步执行脚本,它只允许你执行一个与浏览器主线程异步运行的脚本,比如 AJAX 调用和JavaScript setTimeout
这些JavaScript函数和本身几乎立即返回,但它们需要一个(JavaScript)在异步操作完成时执行的函数参数。execute_async_script的操作与execute_script完全相同,但不是在函数本身返回时返回(几乎是立即)它提供了自己的回调JavaScript函数(它作为最后一个参数传递,这就是为什么需要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应该仅在音频播放完毕时返回。

f0brbegy

f0brbegy2#

用法如下:

# driver allready i initialised

js = """
     var done = arguments[0];
     // my_async_acript here ..
        .then(value=>done(value)
"""
value = driver.execute_async_script(js)

调用javascript函数done(value),其中包含要返回的值。
注意:如果您遇到超时异常,请检查开发人员控制台是否有错误
这实际上是一个重复,我认为reference

gajydyqb

gajydyqb3#

最后传递的参数是promise解析器,这一点很重要,这意味着:

self.browser.execute_async_script("""
  let [element, resolve] = arguments
  element.addEventListener("ended", resolve)    
""", audio)

相关问题