PID(Proportional-Integral-Derivative)算法是一种常用的控制算法,主要用于对各种系统和过程进行自动控制。它基于对系统当前状态的反馈信息,通过计算误差信号的比例、积分和导数部分,来决定控制器输出的大小和方向,从而实现对系统的稳定控制。
具体来说,PID算法包括三个部分:
这三个控制部分共同作用于系统,使得控制器输出的值能够及时、准确地跟随系统的变化,达到对系统的精确控制。
PID 公式u(t) = Kp * e(t) Ki * ∫e(t)dt Kd * de(t)/dt
其中,u(t)是控制器的输出值,e(t)是当前时刻的误差信号(设目标值为r(t),实际值为y(t),则e(t)=r(t)-y(t)),Kp、Ki和Kd分别是比例、积分和导数部分的控制参数。这里不对公式做深入解读,感兴趣的朋友们可去查阅相关资料。这里我们重点需了解 P 、I、D 三个参数各自的含义,后续主要通过调整这三个参数来达到目标效果。
轨迹被检测的原因有些滑块验证存在反爬机制,会出现使用 Selenium 编写滑块移动轨迹后被识别为非人工操作,即使滑块正入缺口也会提示验证失败。为了让轨迹尽可能与人手拖动相似,我们需要注意以下几点:
class PositionalPID:
"""位置式PID系统:位置式指的是将控制器输出与被控对象的位移(位置)进行比较来计算误差,并根据误差大小调整控制器输出的控制方法。在位置式PID系统中,目标是通过控制被控对象的位置来实现精确的控制"""
def __init__(self, P, I, D):
self.Kp = P
self.Ki = I
self.Kd = D
self.SystemOutput = 0.0
self.ResultValueBack = 0.0
self.PidOutput = 0.0
self.PIDErrADD = 0.0
self.ErrBack = 0.0
def SetInertiaTime(self, InertiaTime, SampleTime):
self.SystemOutput = (InertiaTime * self.ResultValueBack SampleTime * self.PidOutput) / (
SampleTime InertiaTime)
self.ResultValueBack = self.SystemOutput
def SetStepSignal(self, StepSignal):
Err = StepSignal - self.SystemOutput
KpWork = self.Kp * Err
KiWork = self.Ki * self.PIDErrADD
KdWork = self.Kd * (Err - self.ErrBack)
self.PidOutput = KpWork KiWork KdWork
self.PIDErrADD = Err
self.ErrBack = Err
def count_pid(P, I, D, li):
PositionalPid = PositionalPID(P, I, D)
PositionalXaxis = [0]
PositionalYaxis = [0]
# 100 次循环模拟滑块移动一段距离的过程,可调参
for i in range(1, 100):
PositionalPid.SetStepSignal(li)
PositionalPid.SetInertiaTime(3, 0.1)
PositionalYaxis.append(PositionalPid.SystemOutput)
PositionalXaxis.append(i)
l = []
for i in range(len(PositionalYaxis) - 1):
l.append(round(PositionalYaxis[i 1] - PositionalYaxis[i]))
return l
def get_pid_track(distance):
'''
可调参
'''
return count_pid(0.1, 0.1, 0.1, distance)
算法封装为 PositionalPID.class,可对 P、I、D 三个参数进行调参,如先控制 0.1,之后以试错法增加减少值大小以达到最佳效果。
def slide_verify(driver, expression, distance):
"""
:param driver: 驱动
:param expression: 滑块元素
:param distance: 滑块到达缺口的距离
:return: chrome Driver
"""
# 获得PID轨迹
track = get_pid_track(distance)
webdriver.ActionChains(driver).click_and_hold(slider_element).perform()
for x in track:
if (x != 0):
# 模拟抖动
offset_y = random.uniform(-2, 2)
webdriver.ActionChains(driver).move_by_offset(xoffset=x, yoffset=offset_y).perform()
time.sleep(0.5)
webdriver.ActionChains(driver).release().perform()
这里通过传入滑块到达缺口的距离得到轨迹数组,同时模拟 Y 轴抖动,遍历数组拖动滑块完成验证。
最后以上就是通过 PID 算法模拟手工拖动滑块的轨迹
感谢您的阅读,如果喜欢本文欢迎关注和转发,转载需注明出处,本头条号将持续分享IT技术知识。对于文章内容有其他想法或意见建议等,欢迎提出共同讨论共同进步。
Copyright © 2024 妖气游戏网 www.17u1u.com All Rights Reserved