本文将介绍如何使用F#语言结合Selenium和OpenCV库来实现对极验滑动验证码的自动破解。整个过程包括模拟点击、获取验证码图片、识别缺口位置、计算滑动轨迹以及模拟滑块拖动。
实现步骤
初始化Selenium WebDriver并打开目标网页。
模拟点击切换至滑动验证模式,并显示验证码图片。
获取验证码背景图和滑块位置。
对比带缺口和无缺口的验证码图片,识别缺口位置。
计算滑动轨迹并模拟拖动滑块。
如果验证失败,重复上述步骤。
F#实现步骤及代码
初始化
首先,初始化Selenium WebDriver对象,并配置参数:
fsharp
open OpenQA.Selenium
open OpenQA.Selenium.Chrome
open OpenQA.Selenium.Support.UI
open System.Drawing
open System.IO
open System
let border = 6
let url = "https://www.geetest.com/type/"
type CrackGeetest() =
let mutable browser = new ChromeDriver()
let wait = new WebDriverWait(browser, TimeSpan.FromSeconds(10.0))
member this.Open() =
browser.Url <- url
member this.Close() =
browser.Close()
browser.Quit()
let crack = CrackGeetest()
crack.Open()
模拟点击
模拟点击以切换到滑动验证模式,并显示验证码图片:
fsharp
member this.ChangeToSlide() =
let huadong = wait.Until(ExpectedConditions.ElementToBeClickable(By.CssSelector(".products-content ul > li:nth-child(2)")))
huadong
member this.GetGeetestButton() =
let button = wait.Until(ExpectedConditions.ElementToBeClickable(By.CssSelector(".geetest_radar_tip")))
button
let slideButton = crack.ChangeToSlide()
slideButton.Click()
let geetestButton = crack.GetGeetestButton()
geetestButton.Click()
获取背景图
等待验证码图片加载完成,获取网页截图,并获取验证背景图的位置及大小:
fsharp
member this.WaitPic() =
wait.Until(ExpectedConditions.PresenceOfAllElementsLocatedBy(By.CssSelector(".geetest_popup_wrap"))) |> ignore
member this.GetScreenshot() =
browser.GetScreenshot().AsByteArray
member this.GetPosition() =
let img = wait.Until(ExpectedConditions.PresenceOfAllElementsLocatedBy(By.ClassName("geetest_canvas_img"))).Item(0)
let location = img.Location
let size = img.Size
(location.Y, location.Y + size.Height, location.X, location.X + size.Width)
member this.GetSlider() =
let slider = wait.Until(ExpectedConditions.ElementToBeClickable(By.ClassName("geetest_slider_button")))
slider
member this.SaveImage(data: byte[], fileName: string) =
use ms = new MemoryStream(data)
let img = Image.FromStream(ms)
img.Save(fileName)
member this.GetGeetestImage(name: string) =
let (top, bottom, left, right) = this.GetPosition()
let screenshot = this.GetScreenshot()
this.SaveImage(screenshot, name)
name
member this.DeleteStyle() =
browser.ExecuteScript("document.querySelectorAll('canvas')[2].style=''") |> ignore
let waitPic = crack.WaitPic()
let slider = crack.GetSlider()
let image1 = crack.GetGeetestImage("captcha1.png")
crack.DeleteStyle()
let image2 = crack.GetGeetestImage("captcha2.png")
识别缺口
通过比较带缺口和无缺口的验证码图片像素,识别缺口位置:
fsharp
let isPixelEqual (img1: Bitmap) (img2: Bitmap) x y =
let threshold = 60
let pix1 = img1.GetPixel(x, y)
let pix2 = img2.GetPixel(x, y)
abs (pix1.R - pix2.R) < threshold &&
abs (pix1.G - pix2.G) < threshold &&
abs (pix1.B - pix2.B) < threshold
member this.GetGap(image1Path: string, image2Path: string) =
use img1 = new Bitmap(image1Path)
use img2 = new Bitmap(image2Path)
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
return left
left
let gap = crack.GetGap("captcha1.png", "captcha2.png")
模拟拖动
计算滑动轨迹并模拟拖动滑块:
fsharp
member this.GetTrack(distance: int) =
let mutable current = 0
let mid = distance * 3 / 5
let t = 0.2
let mutable v = 0.0
let mutable track = []
while current < distance do
let a = if current < mid then 2.0 else -3.0
let v0 = v
v <- v0 + a * t
let move = v0 * t + 0.5 * a * t * t |> int
current <- current + move
track <- track @ [move]
track
member this.MoveToGap(slider: IWebElement, track: int list) =
let actions = new OpenQA.Selenium.Interactions.Actions(browser)
actions.ClickAndHold(slider).Perform()
for t in track do
actions.MoveByOffset(t, 0).Perform()
actions.Release().Perform()
let track = crack.GetTrack(gap - border)
crack.MoveToGap(slider, track)
主体流程
执行主体流程,若验证失败, 则再次调用crack方法进行识别,直至成功:
fsharp
member this.Crack() =
try
this.Open()
let slideButton = this.ChangeToSlide()
slideButton.Click()
let geetestButton = this.GetGeetestButton()
geetestButton.Click()
this.WaitPic()
let slider = this.GetSlider()
let image1 = this.GetGeetestImage("captcha1.png")
this.DeleteStyle()
let image2 = this.GetGeetestImage("captcha2.png")
let gap = this.GetGap("captcha1.png", "captcha2.png")
let track = this.GetTrack(gap - border)
this.MoveToGap(slider, track)
let success = wait.Until(ExpectedConditions.TextToBePresentInElementLocated(By.ClassName("geetest_success_radar_tip_content"), "验证成功"))
printfn "验证成功"
Thread.Sleep(5000)
this.Close()
with
| _ ->
printfn "Failed-Retry"更多内容联系1436423940
this.Crack()
crack.Crack()