问题的引出 Selenium 做模拟滑块的时候能感觉到明显的卡顿
查找原因 这个博文 中有个测试,我自己写了下确实是这样,但是他的解决方式我不能接受,直接修改源代码的话机器多了根本不行的.
然后在这个issues 上看到了作者的相关回答,可以在行为链的时候赋值一个参数做到这样,然后在去看ActionChains
的定义的话确实有这可以这样初始化.
1 2 3 4 5 6 7 8 9 10 11 12 13 class ActionChains : def __init__ (self, driver, duration=250 ): """ Creates a new ActionChains. :Args: - driver: The WebDriver instance which performs user actions. - duration: override the default 250 msecs of DEFAULT_MOVE_DURATION in PointerInput """ self ._driver = driver self ._actions = [] self .w3c_actions = ActionBuilder(driver, duration=duration)
那思路就明确可以不用修改源文件直接在初始化的时候传参数就可以了
代码示例 action_chains 动作可以不附加在元素上执行 而且不会报错,这里我就打开百度跑下看看效果
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 import timefrom selenium import webdriverfrom selenium.webdriver.chrome.service import Servicefrom selenium.webdriver.common.action_chains import ActionChainsfrom selenium.webdriver.support.ui import WebDriverWaitclass Search : def __init__ (self ): option = webdriver.ChromeOptions() option.add_argument('--disable-dev-shm-usage' ) option.add_argument('--disable-gpu' ) option.add_argument('--incognito' ) option.add_argument('--no-sandbox' ) option.add_argument('headless' ) option.binary_location = r'/Applications/Chrome.app/Contents/MacOS/Google Chrome' option.add_argument( 'User-Agent=Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/75.0.3770.100 Safari/537.36' ) option.add_experimental_option('excludeSwitches' , ['enable-automation' ]) service = Service(DRIVER_PATH) self .driver = webdriver.Chrome(service=service, options=option) self .wait = WebDriverWait(self .driver, 10 ) self .action_chains = ActionChains(self .driver, duration=1 ) self .url = "https://www.baidu.com" def __del__ (self ): self .driver.close() def main (self ) self .driver.get(self .url) self .driver.set_window_size(1907 , 1035 ) start_time = time.time() for i in range (1 , 21 ): self .action_chains.move_by_offset(xoffset=0 , yoffset=0 ).perform() now_time = time.time() hs = round ((now_time - start_time), 3 ) start_time = now_time print (f'{i} ,{hs} ' )if __name__ == '__main__' : s = Search() s.main() del s
结果的话确实比之前的间隔短
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 1 ,0.046 2 ,0.037 3 ,0.077 4 ,0.007 5 ,0.019 6 ,0.015 7 ,0.017 8 ,0.017 9 ,0.017 10 ,0.016 11 ,0.018 12 ,0.015 13 ,0.017 14 ,0.018 15 ,0.015 16 ,0.016 17 ,0.019 18 ,0.017 19 ,0.015 20 ,0.017
这个库的作者也贴了一段代码,大致思路就是把move_by_offset 通过更多的step 来让滑块更精细
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 from selenium.webdriver.common.action_chains import ActionChainsclass EnhancedActionChains (ActionChains ): def smooth_move_by_offset (self, dx, dy, n_step=50 ): def get_displacements (): step_x = dx / n_step step_y = dy / n_step for i in range (n_step): yield ( round ((i + 1 ) * step_x) - round (i * step_x), round ((i + 1 ) * step_y) - round (i * step_y), ) self .w3c_actions.pointer_action._duration = 0 for ddx, ddy in get_displacements(): self .w3c_actions.pointer_action.move_by(ddx, ddy) return self