← 返回文章列表

深度解析:滑块验证码通杀方案--python破解代码

本代码理论上可以通杀市面上所有滑块(如果真出现了识别不到,请自行根据文章末尾的参考内容,自己进行调教)在线测试地址:simple_ocr截至2022.7.13,可以破解的有:1、顶象2、网易易盾以下是识别代码:fromioimportByt

本代码理论上可以通杀市面上所有滑块(如果真出现了识别不到,请自行根据文章末尾的参考内容,自己进行调教)

在线测试地址:

simple_ocr

截至2022.7.13,可以破解的有:

1、

顶象

2、

网易易盾

以下是识别代码:

from

io

import

BytesIO

import

onnxruntime

import

torch

import

torchvision

import

numpy

as

np

from

selenium

.

webdriver

.

common

.

by

import

By

from

selenium

.

webdriver

.

chrome

.

options

import

Options

from

selenium

import

webdriver

import

time

import

cv2

import

base64

from

selenium

.

webdriver

import

ActionChains

import

random

from

PIL

import

Image

from

lxml

import

etree

import

requests

def

padded_resize

(

im

,

new_shape

=

(

640

,

640

)

,

stride

=

32

)

:

try

:

shape

=

im

.

shape

[

:

2

]

r

=

min

(

new_shape

[

0

]

/

shape

[

0

]

,

new_shape

[

1

]

/

shape

[

1

]

)

new_unpad

=

int

(

round

(

shape

[

1

]

*

r

)

)

,

int

(

round

(

shape

[

0

]

*

r

)

)

dw

,

dh

=

new_shape

[

1

]

-

new_unpad

[

0

]

,

new_shape

[

0

]

-

new_unpad

[

1

]

# dw, dh = np.mod(dw, stride), np.mod(dh, stride)

dw

/=

2

dh

/=

2

if

shape

[

:

:

-

1

]

!=

new_unpad

:

# resize

im

=

cv2

.

resize

(

im

,

new_unpad

,

interpolation

=

cv2

.

INTER_LINEAR

)

top

,

bottom

=

int

(

round

(

dh

-

0.1

)

)

,

int

(

round

(

dh

+

0.1

)

)

left

,

right

=

int

(

round

(

dw

-

0.1

)

)

,

int

(

round

(

dw

+

0.1

)

)

im

=

cv2

.

copyMakeBorder

(

im

,

top

,

bottom

,

left

,

right

,

cv2

.

BORDER_CONSTANT

,

value

=

(

114

,

114

,

114

)

)

# add border

# Convert

im

=

im

.

transpose

(

(

2

,

0

,

1

)

)

[

:

:

-

1

]

# HWC to CHW, BGR to RGB

im

=

np

.

ascontiguousarray

(

im

)

im

=

torch

.

from_numpy

(

im

)

im

=

im

.

float

(

)

im

/=

255

im

=

im

[

None

]

im

=

im

.

cpu

(

)

.

numpy

(

)

# torch to numpy

return

im

except

:

print

(

"123"

)

def

xywh2xyxy

(

x

)

:

# Convert nx4 boxes from [x, y, w, h] to [x1, y1, x2, y2] where xy1=top-left, xy2=bottom-right

y

=

x

.

clone

(

)

if

isinstance

(

x

,

torch

.

Tensor

)

else

np

.

copy

(

x

)

y

[

:

,

0

]

=

x

[

:

,

0

]

-

x

[

:

,

2

]

/

2

# top left x

y

[

:

,

1

]

=

x

[

:

,

1

]

-

x

[

:

,

3

]

/

2

# top left y

y

[

:

,

2

]

=

x

[

:

,

0

]

+

x

[

:

,

2

]

/

2

# bottom right x

y

[

:

,

3

]

=

x

[

:

,

1

]

+

x

[

:

,

3

]

/

2

# bottom right y

return

y

def

box_iou

(

box1

,

box2

)

:

"""

Return intersection-over-union (Jaccard index) of boxes.

Both sets of boxes are expected to be in (x1, y1, x2, y2) format.

Arguments:

box1 (Tensor[N, 4])

box2 (Tensor[M, 4])

Returns:

iou (Tensor[N, M]): the NxM matrix containing the pairwise

IoU values for every element in boxes1 and boxes2

"""

def

box_area

(

box

)

:

# box = 4xn

return

(

box

[

2

]

-

box

[

0

]

)

*

(

box

[

3

]

-

box

[

1

]

)

area1

=

box_area

(

box1

.

T

)

area2

=

box_area

(

box2

.

T

)

# inter(N,M) = (rb(N,M,2) - lt(N,M,2)).clamp(0).prod(2)

inter

=

(

torch

.

min

(

box1

[

:

,

None

,

2

:

]

,

box2

[

:

,

2

:

]

)

-

torch

.

max

(

box1

[

:

,

None

,

:

2

]

,

box2

[

:

,

:

2

]

)

)

.

clamp

(

0

)

.

prod

(

2

)

return

inter

/

(

area1

[

:

,

None

]

+

area2

-

inter

)

# iou = inter / (area1 + area2 - inter)

def

non_max_suppression

(

prediction

,

conf_thres

=

0.25

,

iou_thres

=

0.45

,

classes

=

None

,

agnostic

=

False

,

multi_label

=

False

,

labels

=

(

)

,

max_det

=

300

)

:

"""Runs Non-Maximum Suppression (NMS) on inference results

Returns:

list of detections, on (n,6) tensor per image [xyxy, conf, cls]

"""

nc

=

prediction

.

shape

[

2

]

-

5

# number of classes

xc

=

prediction

[

.

.

.

,

4

]

>

conf_thres

# candidates

# Checks

assert

0

<=

conf_thres

<=

1

,

f'Invalid Confidence threshold

{

conf_thres

}

, valid values are between 0.0 and 1.0'

assert

0

<=

iou_thres

<=

1

,

f'Invalid IoU

{

iou_thres

}

, valid values are between 0.0 and 1.0'

# Settings

min_wh

,

max_wh

=

2

,

7680

# (pixels) minimum and maximum box width and height

max_nms

=

30000

# maximum number of boxes into torchvision.ops.nms()

time_limit

=

10.0

# seconds to quit after

redundant

=

True

# require redundant detections

multi_label

&

=

nc

>

1

# multiple labels per box (adds 0.5ms/img)

merge

=

False

# use merge-NMS

t

=

time

.

time

(

)

output

=

[

torch

.

zeros

(

(

0

,

6

)

,

device

=

prediction

.

device

)

]

*

prediction

.

shape

[

0

]

for

xi

,

x

in

enumerate

(

prediction

)

:

# image index, image inference

# Apply constraints

x

[

(

(

x

[

.

.

.

,

2

:

4

]

<

min_wh

)

|

(

x

[

.

.

.

,

2

:

4

]

>

max_wh

)

)

.

any

(

1

)

,

4

]

=

0

# width-height

x

=

x

[

xc

[

xi

]

]

# confidence

# Cat apriori labels if autolabelling

if

labels

and

len

(

labels

[

xi

]

)

:

lb

=

labels

[

xi

]

v

=

torch

.

zeros

(

(

len

(

lb

)

,

nc

+

5

)

,

device

=

x

.

device

)

v

[

:

,

:

4

]

=

lb

[

:

,

1

:

5

]

# box

v

[

:

,

4

]

=

1.0

# conf

v

[

range

(

len

(

lb

)

)

,

lb

[

:

,

0

]

.

long

(

)

+

5

]

=

1.0

# cls

x

=

torch

.

cat

(

(

x

,

v

)

,

0

)

# If none remain process next image

if

not

x

.

shape

[

0

]

:

continue

# Compute conf

x

[

:

,

5

:

]

*=

x

[

:

,

4

:

5

]

# conf = obj_conf * cls_conf

# Box (center x, center y, width, height) to (x1, y1, x2, y2)

box

=

xywh2xyxy

(

x

[

:

,

:

4

]

)

# Detections matrix nx6 (xyxy, conf, cls)

if

multi_label

:

i

,

j

=

(

x

[

:

,

5

:

]

>

conf_thres

)

.

nonzero

(

as_tuple

=

False

)

.

T

x

=

torch

.

cat

(

(

box

[

i

]

,

x

[

i

,

j

+

5

,

None

]

,

j

[

:

,

None

]

.

float

(

)

)

,

1

)

else

:

# best class only

conf

,

j

=

x

[

:

,

5

:

]

.

max

(

1

,

keepdim

=

True

)

x

=

torch

.

cat

(

(

box

,

conf

,

j

.

float

(

)

)

,

1

)

[

conf

.

view

(

-

1

)

>

conf_thres

]

# Filter by class

if

classes

is

not

None

:

x

=

x

[

(

x

[

:

,

5

:

6

]

==

torch

.

tensor

(

classes

,

device

=

x

.

device

)

)

.

any

(

1

)

]

# Apply finite constraint

# if not torch.isfinite(x).all():

# x = x[torch.isfinite(x).all(1)]

# Check shape

n

=

x

.

shape

[

0

]

# number of boxes

if

not

n

:

# no boxes

continue

elif

n

>

max_nms

:

# excess boxes

x

=

x

[

x

[

:

,

4

]

.

argsort

(

descending

=

True

)

[

:

max_nms

]

]

# sort by confidence

# Batched NMS

c

=

x

[

:

,

5

:

6

]

*

(

0

if

agnostic

else

max_wh

)

# classes

boxes

,

scores

=

x

[

:

,

:

4

]

+

c

,

x

[

:

,

4

]

# boxes (offset by class), scores

i

=

torchvision

.

ops

.

nms

(

boxes

,

scores

,

iou_thres

)

# NMS

if

i

.

shape

[

0

]

>

max_det

:

# limit detections

i

=

i

[

:

max_det

]

if

merge

and

(

1

<

n

<

3E3

)

:

# Merge NMS (boxes merged using weighted mean)

# update boxes as boxes(i,4) = weights(i,n) * boxes(n,4)

iou

=

box_iou

(

boxes

[

i

]

,

boxes

)

>

iou_thres

# iou matrix

weights

=

iou

*

scores

[

None

]

# box weights

x

[

i

,

:

4

]

=

torch

.

mm

(

weights

,

x

[

:

,

:

4

]

)

.

float

(

)

/

weights

.

sum

(

1

,

keepdim

=

True

)

# merged boxes

if

redundant

:

i

=

i

[

iou

.

sum

(

1

)

>

1

]

# require redundancy

output

[

xi

]

=

x

[

i

]

if

(

time

.

time

(

)

-

t

)

>

time_limit

:

break

# time limit exceeded

return

output

def

xyxy2xywh

(

x

)

:

# Convert nx4 boxes from [x1, y1, x2, y2] to [x, y, w, h] where xy1=top-left, xy2=bottom-right

y

=

x

.

clone

(

)

if

isinstance

(

x

,

torch

.

Tensor

)

else

np

.

copy

(

x

)

y

[

:

,

0

]

=

(

x

[

:

,

0

]

+

x

[

:

,

2

]

)

/

2

# x center

y

[

:

,

1

]

=

(

x

[

:

,

1

]

+

x

[

:

,

3

]

)

/

2

# y center

y

[

:

,

2

]

=

x

[

:

,

2

]

-

x

[

:

,

0

]

# width

y

[

:

,

3

]

=

x

[

:

,

3

]

-

x

[

:

,

1

]

# height

return

y

def

is_ascii

(

s

=

''

)

:

# Is string composed of all ASCII (no UTF) characters? (note str().isascii() introduced in python 3.7)

s

=

str

(

s

)

# convert list, tuple, None, etc. to str

return

len

(

s

.

encode

(

)

.

decode

(

'ascii'

,

'ignore'

)

)

==

len

(

s

)

def

box_label

(

self

,

box

,

label

=

''

,

color

=

(

128

,

128

,

128

)

,

txt_color

=

(

255

,

255

,

255

)

)

:

# Add one xyxy box to image with label

if

self

.

pil

or

not

is_ascii

(

label

)

:

self

.

draw

.

rectangle

(

box

,

width

=

self

.

lw

,

outline

=

color

)

# box

if

label

:

w

,

h

=

self

.

font

.

getsize

(

label

)

# text width, height

outside

=

box

[

1

]

-

h

>=

0

# label fits outside box

self

.

draw

.

rectangle

(

(

box

[

0

]

,

box

[

1

]

-

h

if

outside

else

box

[

1

]

,

box

[

0

]

+

w

+

1

,

box

[

1

]

+

1

if

outside

else

box

[

1

]

+

h

+

1

)

,

fill

=

color

)

# self.draw.text((box[0], box[1]), label, fill=txt_color, font=self.font, anchor='ls') # for PIL>8.0

self

.

draw

.

text

(

(

box

[

0

]

,

box

[

1

]

-

h

if

outside

else

box

[

1

]

)

,

label

,

fill

=

txt_color

,

font

=

self

.

font

)

else

:

# cv2

p1

,

p2

=

(

int

(

box

[

0

]

)

,

int

(

box

[

1

]

)

)

,

(

int

(

box

[

2

]

)

,

int

(

box

[

3

]

)

)

cv2

.

rectangle

(

self

.

im

,

p1

,

p2

,

color

,

thickness

=

self

.

lw

,

lineType

=

cv2

.

LINE_AA

)

if

label

:

tf

=

max

(

self

.

lw

-

1

,

1

)

# font thickness

w

,

h

=

cv2

.

getTextSize

(

label

,

0

,

fontScale

=

self

.

lw

/

3

,

thickness

=

tf

)

[

0

]

# text width, height

outside

=

p1

[

1

]

-

h

-

3

>=

0

# label fits outside box

p2

=

p1

[

0

]

+

w

,

p1

[

1

]

-

h

-

3

if

outside

else

p1

[

1

]

+

h

+

3

cv2

.

rectangle

(

self

.

im

,

p1

,

p2

,

color

,

-

1

,

cv2

.

LINE_AA

)

# filled

cv2

.

putText

(

self

.

im

,

label

,

(

p1

[

0

]

,

p1

[

1

]

-

2

if

outside

else

p1

[

1

]

+

h

+

2

)

,

0

,

self

.

lw

/

3

,

txt_color

,

thickness

=

tf

,

lineType

=

cv2

.

LINE_AA

)

def

return_coordinates

(

xyxy

,

conf

)

:

conf

=

float

(

conf

.

numpy

(

)

)

gain

=

1.02

pad

=

10

xyxy

=

torch

.

tensor

(

xyxy

)

.

view

(

-

1

,

4

)

b

=

xyxy2xywh

(

xyxy

)

# boxes

b

[

:

,

2

:

]

=

b

[

:

,

2

:

]

*

gain

+

pad

# box wh * gain + pad

xyxy

=

xywh2xyxy

(

b

)

.

long

(

)

c1

,

c2

=

(

int

(

xyxy

[

0

,

0

]

)

+

6

,

int

(

xyxy

[

0

,

1

]

)

+

6

)

,

(

int

(

xyxy

[

0

,

2

]

)

-

6

,

int

(

xyxy

[

0

,

3

]

)

-

6

)

# print(f"leftTop:{c1},rightBottom:{c2},Confidence:{conf*100}%")

result_dict

=

{

"leftTop"

:

c1

,

"rightBottom"

:

c2

,

"Confidence"

:

conf

}

return

result_dict

def

clip_coords

(

boxes

,

shape

)

:

# Clip bounding xyxy bounding boxes to image shape (height, width)

if

isinstance

(

boxes

,

torch

.

Tensor

)

:

# faster individually

boxes

[

:

,

0

]

.

clamp_

(

0

,

shape

[

1

]

)

# x1

boxes

[

:

,

1

]

.

clamp_

(

0

,

shape

[

0

]

)

# y1

boxes

[

:

,

2

]

.

clamp_

(

0

,

shape

[

1

]

)

# x2

boxes

[

:

,

3

]

.

clamp_

(

0

,

shape

[

0

]

)

# y2

else

:

# np.array (faster grouped)

boxes

[

:

,

[

0

,

2

]

]

=

boxes

[

:

,

[

0

,

2

]

]

.

clip

(

0

,

shape

[

1

]

)

# x1, x2

boxes

[

:

,

[

1

,

3

]

]

=

boxes

[

:

,

[

1

,

3

]

]

.

clip

(

0

,

shape

[

0

]

)

# y1, y2

def

scale_coords

(

img1_shape

,

coords

,

img0_shape

,

ratio_pad

=

None

)

:

# Rescale coords (xyxy) from img1_shape to img0_shape

if

ratio_pad

is

None

:

# calculate from img0_shape

gain

=

min

(

img1_shape

[

0

]

/

img0_shape

[

0

]

,

img1_shape

[

1

]

/

img0_shape

[

1

]

)

# gain = old / new

pad

=

(

img1_shape

[

1

]

-

img0_shape

[

1

]

*

gain

)

/

2

,

(

img1_shape

[

0

]

-

img0_shape

[

0

]

*

gain

)

/

2

# wh padding

else

:

gain

=

ratio_pad

[

0

]

[

0

]

pad

=

ratio_pad

[

1

]

coords

[

:

,

[

0

,

2

]

]

-=

pad

[

0

]

# x padding

coords

[

:

,

[

1

,

3

]

]

-=

pad

[

1

]

# y padding

coords

[

:

,

:

4

]

/=

gain

clip_coords

(

coords

,

img0_shape

)

return

coords

def

onnx_model_main

(

path

)

:

# onnx

session

=

onnxruntime

.

InferenceSession

(

"last.onnx"

,

providers

=

[

"CPUExecutionProvider"

]

)

start

=

time

.

time

(

)

image

=

open

(

path

,

"rb"

)

.

read

(

)

img

=

np

.

array

(

Image

.

open

(

BytesIO

(

image

)

)

)

# img = cv2.imread(path)

# 图像处理

img

=

img

[

:

,

:

,

:

3

]

im

=

padded_resize

(

img

)

# 模型调度

pred

=

session

.

run

(

[

session

.

get_outputs

(

)

[

0

]

.

name

]

,

{

session

.

get_inputs

(

)

[

0

]

.

name

:

im

}

)

[

0

]

pred

=

torch

.

tensor

(

pred

)

pred

=

non_max_suppression

(

pred

,

conf_thres

=

0.25

,

iou_thres

=

0.60

,

max_det

=

1000

)

# 大于百分之六十的置信度

coordinate_list

=

[

]

for

i

,

det

in

enumerate

(

pred

)

:

det

[

:

,

:

4

]

=

scale_coords

(

im

.

shape

[

2

:

]

,

det

[

:

,

:

4

]

,

img

.

shape

)

.

round

(

)

for

*

xyxy

,

conf

,

cls

in

reversed

(

det

)

:

# 返回坐标和置信度

coordinates

=

return_coordinates

(

xyxy

,

conf

)

coordinate_list

.

append

(

coordinates

)

# 坐标列表

coordinate

=

sorted

(

coordinate_list

,

key

=

lambda

a

:

a

[

"Confidence"

]

)

# 用时

duration

=

str

(

(

time

.

time

(

)

-

start

)

)

if

len

(

coordinate

)

==

0

:

data

=

{

'message'

:

'error'

,

'time'

:

duration

}

else

:

coordinate

=

coordinate

[

-

1

]

x

=

coordinate

.

get

(

'leftTop'

)

[

0

]

y

=

coordinate

.

get

(

'leftTop'

)

[

1

]

w

=

coordinate

.

get

(

'rightBottom'

)

[

0

]

-

coordinate

.

get

(

'leftTop'

)

[

0

]

h

=

coordinate

.

get

(

'rightBottom'

)

[

1

]

-

coordinate

.

get

(

'leftTop'

)

[

1

]

point

=

f"

{

x

}

|

{

y

}

|

{

w

}

|

{

h

}

"

data

=

{

'message'

:

'success'

,

'time'

:

duration

,

'point'

:

point

}

data

.

update

(

coordinate

)

print

(

data

)

return

data

def

drow_rectangle

(

coordinate

,

path

)

:

img

=

cv2

.

imread

(

path

)

# 画框

result

=

cv2

.

rectangle

(

img

,

coordinate

.

get

(

"leftTop"

)

,

coordinate

.

get

(

"rightBottom"

)

,

(

0

,

0

,

255

)

,

2

)

cv2

.

imwrite

(

"drow_rectangle.jpg"

,

result

)

# 返回圈中矩形的图片

print

(

"返回坐标矩形成功"

)

调用方法:

coordinate_onnx

=

onnx_model_main

(

"1.png"

)

#需要识别的图片路径

#返回内容

#{'message': 'success', 'time': '0.5251204967498779', 'point': '260|90|59|56', 'leftTop': (260, 90), 'rightBottom': (319, 146), 'Confidence': 0.31054314970970154}

#

#这个是根据返回信息在同级目录下生成一个加了框的图片

drow_rectangle

(

coordinate_onnx

,

"1.png"

)

#需要识别的图片路径

效果类似于这样子

附带个顶象的测试代码,基于selenium的:(这俩放一起就行,别问我为什么不是协议,问就是不会行了吧)

class

Test

(

)

:

def

__init__

(

self

)

:

option

=

Options

(

)

option

.

add_experimental_option

(

'excludeSwitches'

,

[

'enable-automation'

]

)

option

.

add_argument

(

'--disable-blink-features=AutomationControlled'

)

self

.

driver

=

webdriver

.

Chrome

(

options

=

option

)

def

__ease_out_expo

(

self

,

sep

)

:

if

sep

==

1

:

return

1

else

:

return

1

-

pow

(

2

,

-

10

*

sep

)

def

generate_tracks

(

self

,

distance

)

:

"""

根据滑动距离生成滑动轨迹

:param distance: 需要滑动的距离

:return: 滑动轨迹<type 'list'>: [[x,y,t], ...]

x: 已滑动的横向距离

y: 已滑动的纵向距离, 除起点外, 均为0

t: 滑动过程消耗的时间, 单位: 毫秒

"""

if

not

isinstance

(

distance

,

int

)

or

distance

<

0

:

raise

ValueError

(

f"distance类型必须是大于等于0的整数: distance:

{

distance

}

, type:

{

type

(

distance

)

}

"

)

# 初始化轨迹列表

slide_track

=

[

[

random

.

randint

(

-

50

,

-

10

)

,

random

.

randint

(

-

50

,

-

10

)

,

0

]

,

[

0

,

0

,

0

]

,

]

# 共记录count次滑块位置信息

count

=

30

+

int

(

distance

/

2

)

# 初始化滑动时间

t

=

random

.

randint

(

50

,

100

)

# 记录上一次滑动的距离

_x

=

0

_y

=

0

for

i

in

range

(

count

)

:

# 已滑动的横向距离

x

=

round

(

self

.

__ease_out_expo

(

i

/

count

)

*

distance

)

# 滑动过程消耗的时间

t

+=

random

.

randint

(

10

,

20

)

if

x

==

_x

:

continue

slide_track

.

append

(

[

x

,

_y

,

t

]

)

_x

=

x

slide_track

.

append

(

slide_track

[

-

1

]

)

return

slide_track

# 顶象测试

def

dx_test

(

self

)

:

url

=

'https://www.dingxiang-inc.com/business/captcha?utm_source=baidu1sem&utm_medium=%E4%BA%A7%E5%93%81%E8%AF%8D&utm_campaign=%E4%BA%A7%E5%93%81%E8%AF%8D-%E9%AA%8C%E8%AF%81%E7%A0%81&utm_term=%E9%AA%8C%E8%AF%81%E7%A0%81&e_matchtype=1&e_keywordid=317912325143&bd_vid=9281303599717237405'

# Chrome浏览器

self

.

driver

.

get

(

url

=

url

)

# //li[@class="item-2"]/h3

self

.

driver

.

maximize_window

(

)

# 滑动到最底部

js_button

=

'q=document.body.scrollTop=500'

# 执行js,滑动到最底部

self

.

driver

.

execute_script

(

js_button

)

self

.

driver

.

find_element

(

By

.

XPATH

,

'//li[@class="item-2"]/h3'

)

.

click

(

)

time

.

sleep

(

2

)

self

.

driver

.

find_element

(

By

.

XPATH

,

'//div[@id="dx_captcha_oneclick_bar-inform_3"]'

)

.

click

(

)

time

.

sleep

(

2

)

self

.

download_yzm

(

)

distence

=

onnx_model_main

(

'1.png'

)

drow_rectangle

(

distence

,

'1.png'

)

time

.

sleep

(

1

)

distence

=

int

(

distence

[

'leftTop'

]

[

0

]

)

-

30

source

=

self

.

driver

.

find_element

(

By

.

XPATH

,

'//div[@id="dx_captcha_basic_slider-img-animated-wrap_4"]/span[1]'

)

action

=

ActionChains

(

self

.

driver

,

duration

=

20

)

action

.

click_and_hold

(

source

)

a

=

0

time

.

sleep

(

1

)

for

x

in

self

.

generate_tracks

(

distence

)

:

print

(

x

)

action

.

move_by_offset

(

xoffset

=

x

[

0

]

-

a

,

yoffset

=

x

[

1

]

)

a

=

x

[

0

]

time

.

sleep

(

0.5

)

action

.

release

(

)

.

perform

(

)

input

(

)

# 网易测试

def

wy_test

(

self

)

:

url

=

'https://dun.163.com/trial/jigsaw'

# Chrome浏览器

self

.

driver

.

get

(

url

=

url

)

self

.

driver

.

maximize_window

(

)

js_button

=

'q=document.body.scrollTop=500'

# 执行js,滑动到最底部

self

.

driver

.

execute_script

(

js_button

)

self

.

driver

.

find_element

(

By

.

XPATH

,

'//li[@class="tcapt-tabs__tab"][1]'

)

.

click

(

)

time

.

sleep

(

2

)

self

.

driver

.

find_element

(

By

.

XPATH

,

'//button[@class="yidun_refresh"]'

)

.

click

(

)

html

=

self

.

driver

.

page_source

html

=

etree

.

HTML

(

html

)

url

=

html

.

xpath

(

'//img[@class="yidun_bg-img"]/@src'

)

[

0

]

response

=

requests

.

get

(

url

)

print

(

url

)

with

open

(

'1.png'

,

'wb'

)

as

f

:

f

.

write

(

response

.

content

)

time

.

sleep

(

2

)

input

(

11111111111111

)

self

.

download_yzm

(

)

distence

=

onnx_model_main

(

'1.png'

)

drow_rectangle

(

distence

,

'1.png'

)

time

.

sleep

(

1

)

distence

=

int

(

distence

[

'leftTop'

]

[

0

]

)

-

30

source

=

self

.

driver

.

find_element

(

By

.

XPATH

,

'//div[@id="dx_captcha_basic_slider-img-animated-wrap_4"]/span[1]'

)

action

=

ActionChains

(

self

.

driver

,

duration

=

20

)

action

.

click_and_hold

(

source

)

a

=

0

time

.

sleep

(

1

)

for

x

in

self

.

generate_tracks

(

distence

)

:

print

(

x

)

action

.

move_by_offset

(

xoffset

=

x

[

0

]

-

a

,

yoffset

=

x

[

1

]

)

a

=

x

[

0

]

time

.

sleep

(

0.5

)

action

.

release

(

)

.

perform

(

)

input

(

)

# 测试代码用到的下载图片的东西

def

download_yzm

(

self

)

:

js

=

"return document.querySelector('.dx_captcha_basic_bg > canvas').toDataURL('image/png')"

image_data

=

self

.

driver

.

execute_script

(

js

)

# 执行js代码得到图片数据

data

=

image_data

.

split

(

','

)

[

1

]

image_data

=

base64

.

b64decode

(

data

)

with

open

(

'1.png'

,

'wb'

)

as

f

:

f

.

write

(

image_data

)

if

__name__

==

'__main__'

:

a

=

Test

(

)

a

.

dx_test

(

)

# coordinate_onnx = onnx_model_main("1.png")

# drow_rectangle(coordinate_onnx, "1.png")

可能出现的错误:

1、xpath定位错误

2 、action = ActionChains(self.driver,duration=20) 这里报错

3、self.driver.find_element(By.XPATH,‘xxx"]’).click()这里报错

4、 self.driver = webdriver.Chrome(options=option)这里报错

5、环境问题

解决方法:

1、自己改改嘛,挺简单的。

2、删掉duration=20就好了 或 升级下selenium版本。

3、改成find_element_by_xpath(‘xxx’) 或 升级下selenium版本。

4、指定下chromedriver.exe位置 或 放在python目录下。

5、仅仅是用的话笔者提供的示例的话,应该没啥问题吧…应该,实在不行加我qq问吧(请我吃根棒棒糖就可以了!我这里棒棒糖仅需5毛!!!)

模型下载:

1、csdn下载:

通用滑块验证码识别模型

(我设置的0积分,如果收费了记得给我说下,或者直接加我,问我要也可以)

2、百度云下载: https://pan.baidu.com/s/1Nt2Z2Pu45RaQBs4dsS2kKg?pwd=82xg

提取码:82xg (老慢了)

3、github:暂无

百度云下载方式更新在了github

github:

https://github.com/Bump-mann/simple_ocr

测试:http://121.4.108.95:8000/index/

参考:

1、

深度学习训练滑动验证码(Yolov5)

2、

【Yolov5】1.认真总结6000字Yolov5保姆级教程(全新版本2022.06.28)

---------------------------------------笔者碎碎念---------------------------------------

本来吧,是想先出旋转验证码的,代码都写好了,但是大家都想看滑块的,就先出滑块的啦…

开始做的时候想着就图片处理嘛,蛮简单的,结果…一家一个类型,参数没法写死,不同的图片不同的算法效果不稳定,全是坑,被逼无奈改成写模型了

什么?你问我代码能通杀吗?能,当然能,前提是你数据量够

观众老爷:你这不是欺负老人吗?标题党系内!

笔者:阿巴阿巴,如果催的人多的话,我会持续更新的,做到真正的通杀

本代码的数据标注都是笔者个人一个框一个框标注的,呜呜呜,我也想对接打码平台啊,穷啊