pyppeteer 有提供鼠标滑动的方法,但是单独调用 pyppeteer 滑动方法是无法通过验证的,必须使滑动轨迹更加接近人工的方式才行。
这里我们先了解一下pyppeteer是如何实现滑动的
一、pyppeteer 提供的滑动方法API
-
iframe.hover(slide_id) # 移动鼠标到滑块上方(聚焦)
-
page.mouse.down() # 按下鼠标
-
page.mouse.move() # 移动鼠标
-
page.mouse.up() # 松开鼠标
根据以上的4个方法组合就可以实现滑动。
二、滑动方法API详解
- 1.1 iframe.hover(slide_id) , slide_id是滑块的css选择器,例如'span#nc_1_n1z', 这个根据实际情况来指定。
这里需要注意的是iframe,什么意思呢?很多人给的参考都是直接调用page.hover(slide_id) ,但是很多情况在page里直接找调用hover(slide_id)是无法聚焦到滑块上的,这是因为滑块往往会加载在一个子页面 iframe 上,我们需要在找到 iframe ,然后在 iframe 上调用 hover 来聚焦滑块。
如果滑块已经页面page中,则直接调用 page.hover(slide_id), 无需这么复杂
-
1.2 如何找到 iframe
屏幕快照 2019-08-01 15.01.33.png
首先F12调出元素检查,查看滑块所在的窗口是否有 iframe,(或者直接 ctrl + f 搜索 iframe),
1.找出 iframe 的css选择器 :iframe#sufei-dialog-content (你应该根据实际情况填写)
2.在page中找到此 WebElement元素节点: iframe_element = await page.J('iframe#sufei-dialog-content')
此时还 无法在 iframe_element 上调用hover() 函数,因为iframe_element此时是 ElementHandle Class,而我们需要的是Frame Class
3.将ElementHandle Class强转成Frame Class :iframe =await iframe_element.contentFrame()
完整的方法应该是:
async def iframe_id2frame(iframe_id, page)
iframe_element = await page.J(iframe_id)
if iframe_element:
iframe =await iframe_element.contentFrame()
return iframe
else:
return None
slide_id = '#span……'
iframe_id = 'iframe.sd……'
iframe = await iframe_id2frame(iframe_id)
if iframe:
iframe.hover(slide_id)
-
2 page.mouse.down() 按下鼠标
这个没什么好说的,直接执行就好 -
3 page.mouse.move()
源码:async def move(self, x: float, y: float, options: dict = None,
**kwargs: Any) -> None:源码链接
其中x,y 是指移动到绝对横向,纵向坐标,options是一个字典,只有一个键steps,用来控制速度。
例如你想要鼠标向右移动500像素,则 x为当前横坐标 + 500,y为当前纵坐标不变。
当前的横坐标、纵坐标获取有些麻烦,网上也有人这样来滑动:
await page.mouse(10000,0) ,这样是指把鼠标横行移动到10000,纵向移动到零,滑动无法纵向移动,所以只能看到横行的移动效果。没有添加第三个参数,则默认一步完成 {'steps':1}
注意:这里的坐标和像素值是一致的,左上角为起点(0,0)
steps 是指分成几步来完成,steps越大,滑动速度越慢。(在源码中,steps是指移动到指定x,y 分段滑动的次数,但是每次启动滑动都会花费一定时间,可以认为steps是滑动的速度)
- 4 page.mouse.up() 松开鼠标
到现在,我们已经完成了滑动验证的功能,当然它还不够完善,但基本的功能已经齐全了,在下一节,介绍一下控制滑动轨迹,模拟人工滑动。
async def iframe_id2frame(iframe_id, page)
iframe_element = await page.J(iframe_id)
if iframe_element:
iframe =await iframe_element.contentFrame()
return iframe
else:
return None
# 1 聚焦
slide_id = '#span……'
iframe_id = 'iframe.sd……'
iframe = await iframe_id2frame(iframe_id)
if iframe:
# 如果滑块在页面page中,则直接调用 page.hover(slide_id),无需这么复杂
await iframe.hover(slide_id)
# 2 按下鼠标
await page.mouse.down()
# 3 滑动
await page.mouse.move(10000,0)
# 4 松开鼠标
await page.mouse.up()
注意1:这里pyppeteer涉及到 page 与 iframe,peppeteer的功能是以frame为基础单位来实现的,page 的功能 iframe 都有,page 在执行函数时,会先调用 frame = self.mainFrame,然后在frame上执行功能。mainFrame就是最外面的那个Frame
注意2: mouse对象是page/mainFrame对象所独有的,在子frame中,也就是iframe 中不能调用mouse对象。
网友评论