本文将展示如何使用OCaml实现极验滑动验证码的自动识别。从模拟点击到识别滑动缺口、计算位移并模拟拖动滑块。如果认证失败,则重复调用直到成功。
识别思路
模拟点击切换为滑动验证,并显示验证界面。
识别滑动缺口的位置,计算位移。
模拟拖动滑块。
若认证失败,重复调用。
详细过程及代码
初始化
首先,初始化Selenium WebDriver对象并配置参数。极验验证码测试页面的网址如下:更多内容联系1436423940
ocaml
open Selenium
open Selenium_webdriver
open Images
open Unix
let border = 6
class crackGeetest =
object (self)
val mutable browser = Webdriver.create ~name:"chrome" ()
val url = "https://www.geetest.com/type/"
method open_browser =
ignore (Webdriver.get browser url)
method close_browser =
Webdriver.quit browser
method wait_for_element selector =
let rec wait_element time_left =
if time_left <= 0. then None
else
try Some (Webdriver.find_element browser selector)
with Not_found ->
Unix.sleepf 0.5;
wait_element (time_left -. 0.5)
in
wait_element 10.
method change_to_slide =
match self#wait_for_element (By.css_selector ".products-content ul > li:nth-child(2)") with
| Some elem -> Webdriver.click elem
| None -> failwith "Slide option not found"
method get_geetest_button =
match self#wait_for_element (By.css_selector ".geetest_radar_tip") with
| Some elem -> Webdriver.click elem
| None -> failwith "Geetest button not found"
method wait_pic =
ignore (self#wait_for_element (By.css_selector ".geetest_popup_wrap"))
method get_slider =
match self#wait_for_element (By.class_name "geetest_slider_button") with
| Some elem -> elem
| None -> failwith "Slider not found"
method get_screenshot =
let screenshot = Webdriver.screenshot_as_base64 browser in
Base64.decode_exn screenshot |> Cstruct.of_string |> ImageLib.read_screenshot
method get_position () =
match self#wait_for_element (By.class_name "geetest_canvas_img") with
| Some elem ->
let location = Webdriver.location elem in
let size = Webdriver.size elem in
(location.Webdriver.y, location.Webdriver.y + size.Webdriver.height,
location.Webdriver.x, location.Webdriver.x + size.Webdriver.width)
| None -> failwith "Captcha image not found"
method get_geetest_image name =
let top, bottom, left, right = self#get_position () in
let screenshot = self#get_screenshot in
let captcha = ImageLib.crop screenshot (left, top, right - left, bottom - top) in
ImageLib.save captcha name;
captcha
method delete_style =
ignore (Webdriver.execute_script browser "document.querySelectorAll('canvas')[2].style=''" [])
method is_pixel_equal img1 img2 x y =
let c1 = ImageLib.get_pixel img1 x y in
let c2 = ImageLib.get_pixel img2 x y in
let threshold = 60 in
abs (c1.r - c2.r) < threshold && abs (c1.g - c2.g) < threshold && abs (c1.b - c2.b) < threshold
method get_gap img1 img2 =
let rec find_gap x =
if x >= ImageLib.width img1 then failwith "Gap not found"
else if List.exists (fun y -> not (self#is_pixel_equal img1 img2 x y)) (0 -- (ImageLib.height img1 - 1)) then x
else find_gap (x + 1)
in
find_gap 60
method get_track distance =
let rec compute_track acc current v0 =
if current >= distance then List.rev acc
else
let a = if current < distance * 3 / 5 then 2. else -1.5 in
let t = 0.2 in
let v = v0 +. a *. t in
let move = int_of_float (v0 *. t +. 0.5 *. a *. t *. t) in
compute_track (move :: acc) (current + move) v
in
compute_track [] 0 0.0
method move_to_gap slider tracks =
let actions = Webdriver.Actions.create browser in
Webdriver.Actions.click_and_hold actions slider;
List.iter (fun x -> Webdriver.Actions.move_by_offset actions x 0) tracks;
Webdriver.Actions.release actions
method crack =
self#open_browser;
self#change_to_slide;
self#get_geetest_button;
self#wait_pic;
let slider = self#get_slider in
let image1 = self#get_geetest_image "captcha1.png" in
self#delete_style;
let image2 = self#get_geetest_image "captcha2.png" in
let gap = self#get_gap image1 image2 - border in
let track = self#get_track gap in
self#move_to_gap slider track;
Unix.sleep 5;
self#close_browser
end
let () =
let crack = new crackGeetest in
crack#crack