本文将展示如何使用F#实现极验滑动验证码的自动识别。从模拟点击到识别滑动缺口、计算位移并模拟拖动滑块。如果认证失败,则重复调用直到成功。
识别思路
模拟点击切换为滑动验证,并显示验证界面。
识别滑动缺口的位置,计算位移。
模拟拖动滑块。
若认证失败,重复调用。
详细过程及代码
初始化
首先,初始化Selenium WebDriver对象并配置参数。极验验证码测试页面的网址如下:
fsharp
open OpenQA.Selenium
open OpenQA.Selenium.Chrome
open OpenQA.Selenium.Support.UI
open System.Drawing
open System.IO
open System.Threading
let border = 6
type CrackGeetest() =
let url = "https://www.geetest.com/type/"
let browser = new ChromeDriver()
let wait = new WebDriverWait(browser, System.TimeSpan.FromSeconds(10.0))
member _.Open() =
browser.Navigate().GoToUrl(url)
member _.Close() =
browser.Quit()
member _.ChangeToSlide() =
wait.Until(fun driver -> driver.FindElement(By.CssSelector(".products-content ul > li:nth-child(2)"))).Click()
member _.GetGeetestButton() =
wait.Until(fun driver -> driver.FindElement(By.CssSelector(".geetest_radar_tip"))).Click()
member _.WaitPic() =
wait.Until(fun driver -> driver.FindElement(By.CssSelector(".geetest_popup_wrap")))
member _.GetSlider() =
wait.Until(fun driver -> driver.FindElement(By.ClassName("geetest_slider_button")))
member _.GetScreenshot() =
let screenshot = browser.GetScreenshot()
let imageBytes = screenshot.AsByteArray
Image.FromStream(new MemoryStream(imageBytes))
member _.GetPosition() =
let img = wait.Until(fun driver -> driver.FindElement(By.ClassName("geetest_canvas_img")))
Thread.Sleep(2000)
let location = img.Location
let size = img.Size
(location.Y, location.Y + size.Height, location.X, location.X + size.Width)
member _.GetGeetestImage(name: string) =
let (top, bottom, left, right) = _.GetPosition()
printfn "验证码位置: %d, %d, %d, %d" top bottom left right
let screenshot = _.GetScreenshot()
let cropRect = Rectangle(left, top, right - left, bottom - top)
let target = new Bitmap(cropRect.Width, cropRect.Height)
use g = Graphics.FromImage(target)
g.DrawImage(screenshot, Rectangle(0, 0, target.Width, target.Height), cropRect, GraphicsUnit.Pixel)
target.Save(name)
target
member _.DeleteStyle() =
browser.ExecuteScript("document.querySelectorAll('canvas')[2].style=''") |> ignore
member _.IsPixelEqual(img1: Image, img2: Image, x: int, y: int) =
let bmp1 = img1 :?> Bitmap
let bmp2 = img2 :?> Bitmap
let c1 = bmp1.GetPixel(x, y)
let c2 = bmp2.GetPixel(x, y)
let threshold = 60
abs (c1.R - c2.R) < threshold && abs (c1.G - c2.G) < threshold && abs (c1.B - c2.B) < threshold
member _.GetGap(img1: Image, img2: Image) =
let mutable left = 60
for i in left .. (img1.Width - 1) do
for j in 0 .. (img1.Height - 1) do
if not (_.IsPixelEqual(img1, img2, i, j)) then
left <- i
break
left
member _.GetTrack(distance: int) =
let mutable current = 0
let mid = distance * 3 / 5
let t = 0.2
let mutable v = 0.0
let mutable track = []
let distance = distance + 14
while current < distance do
let a = if current < mid then 2.0 else -1.5
let v0 = v
v <- v0 + a * t
let move = v0 * t + 0.5 * a * t * t |> int
current <- current + move
track <- move :: track
List.rev track
member _.ShakeMouse() =
let actions = new OpenQA.Selenium.Interactions.Actions(browser)
actions.MoveByOffset(-3, 0).Perform()
actions.MoveByOffset(2, 0).Perform()
member _.MoveToGap(slider: IWebElement, tracks: int list) =
let actions = new OpenQA.Selenium.Interactions.Actions(browser)
actions.ClickAndHold(slider).Perform()
for x in tracks do
actions.MoveByOffset(x, 0).Perform()
actions.Release().Perform()
_.ShakeMouse()
Thread.Sleep(500)
member _.Crack() =
try
_.Open()
_.ChangeToSlide()
_.GetGeetestButton()
_.WaitPic()
let slider = _.GetSlider()
let image1 = _.GetGeetestImage("captcha1.png")
_.DeleteStyle()
let image2 = _.GetGeetestImage("captcha2.png")
let gap = _.GetGap(image1, image2) - border
let track = _.GetTrack(gap)
_.MoveToGap(slider, track)
wait.Until(fun driver -> driver.FindElement(By.ClassName("geetest_success_radar_tip_content")).Text.Contains("验证成功")) |> ignore
printfn "验证成功"
Thread.Sleep(5000)
_.Close()
with
| ex ->
printfn "Failed-Retry: %s" ex.Message
_.Crack()
[<EntryPoint>]
let main argv =
let crack = CrackGeetest()
crack.Crack()
0
详细实现
在这篇文章中,我们使用F#实现了极验滑动验证码的识别。代码中使用了Selenium库来操作浏览器,通过模拟点击、获取验证码图片、计算滑动距离,并最终完成滑块拖动验证。