基于小图片合成的大图片滑块的处理代码
导入相关包
from selenium import webdriver
from selenium. webdriver. support. wait import WebDriverWait
from selenium. webdriver. support import expected_conditions as EC
from selenium. webdriver. common. by import By
from selenium. webdriver import ActionChains
from urllib. request import urlretrieve
from bs4 import BeautifulSoup
import re
from PIL import Image
from time import sleep
用的是模拟B站登录,相关drive.exe根据自己的配置去修改
def init ( ) :
global url, browser, username, password, wait
url = 'https://passport.bilibili.com/login'
browser = webdriver. Chrome( './driver.exe' )
username = '***********'
password = '***********'
wait = WebDriverWait( browser, 20 )
根据自己的登录页面可以修改,不一定是账号密码,也有可能是电话号码什么的
def login ( ) :
browser. get( url)
user = wait. until( EC. presence_of_element_located( ( By. ID, 'login-username' ) ) )
passwd = wait. until( EC. presence_of_element_located( ( By. ID, 'login-passwd' ) ) )
user. send_keys( username)
passwd. send_keys( password)
图片处理
def get_image_info ( img) :
'''
:param img: (Str)想要获取的图片类型:带缺口、原始
:return: 该图片(Image)、位置信息(List)
'''
soup = BeautifulSoup( browser. page_source, 'lxml' )
imgs = soup. find_all( 'div' , { 'class' : 'gt_cut_' + img+ '_slice' } )
img_url = re. findall( 'url\(\"(.*)\"\);' , imgs[ 0 ] . get( 'style' ) ) [ 0 ] . replace( 'webp' , 'jpg' )
urlretrieve( url= img_url, filename= img+ '.jpg' )
image = Image. open ( img+ '.jpg' )
position = get_position( imgs)
return image, position
def get_position ( img) :
'''
:param img: (List)存放多个小图片的标签
:return: (List)每个小图片的位置信息
'''
img_position = [ ]
for small_img in img:
position = { }
position[ 'x' ] = int ( re. findall( 'background-position: (.*)px (.*)px;' , small_img. get( 'style' ) ) [ 0 ] [ 0 ] )
position[ 'y' ] = int ( re. findall( 'background-position: (.*)px (.*)px;' , small_img. get( 'style' ) ) [ 0 ] [ 1 ] )
img_position. append( position)
return img_position
def Corp ( image, position) :
'''
:param image:(Image)被裁剪的图片
:param position: (List)该图片的位置信息
:return: (List)存放裁剪后的每个图片信息
'''
first_line_img = [ ]
second_line_img = [ ]
for pos in position:
if pos[ 'y' ] == - 58 :
first_line_img. append( image. crop( ( abs ( pos[ 'x' ] ) , 58 , abs ( pos[ 'x' ] ) + 10 , 116 ) ) )
if pos[ 'y' ] == 0 :
second_line_img. append( image. crop( ( abs ( pos[ 'x' ] ) , 0 , abs ( pos[ 'x' ] ) + 10 , 58 ) ) )
return first_line_img, second_line_img
def put_imgs_together ( first_line_img, second_line_img, img_name) :
'''
:param first_line_img: (List)第一行图片位置信息
:param second_line_img: (List)第二行图片信息
:return: (Image)拼接后的正确顺序的图片
'''
image = Image. new( 'RGB' , ( 260 , 116 ) )
offset = 0
for img in first_line_img:
image. paste( img, ( offset, 0 ) )
offset += img. size[ 0 ]
x_offset = 0
for img in second_line_img:
image. paste( img, ( x_offset, 58 ) )
x_offset += img. size[ 0 ]
image. save( img_name)
return image
def is_pixel_equal ( bg_image, fullbg_image, x, y) :
"""
:param bg_image: (Image)缺口图片
:param fullbg_image: (Image)完整图片
:param x: (Int)位置x
:param y: (Int)位置y
:return: (Boolean)像素是否相同
"""
bg_pixel = bg_image. load( ) [ x, y]
fullbg_pixel = fullbg_image. load( ) [ x, y]
threshold = 60
if ( abs ( bg_pixel[ 0 ] - fullbg_pixel[ 0 ] < threshold) and abs ( bg_pixel[ 1 ] - fullbg_pixel[ 1 ] < threshold) and abs ( bg_pixel[ 2 ] - fullbg_pixel[ 2 ] < threshold) ) :
return True
else :
return False
def get_distance ( bg_image, fullbg_image) :
'''
:param bg_image: (Image)缺口图片
:param fullbg_image: (Image)完整图片
:return: (Int)缺口离滑块的距离
'''
distance = 57
for i in range ( distance, fullbg_image. size[ 0 ] ) :
for j in range ( fullbg_image. size[ 1 ] ) :
if not is_pixel_equal( fullbg_image, bg_image, i, j) :
return i
移动滑块,这里的初始速度可以修改的,根据自己情况去调
def get_trace ( distance) :
'''
:param distance: (Int)缺口离滑块的距离
:return: (List)移动轨迹
'''
trace = [ ]
faster_distance = distance* ( 4 / 5 )
start, v0, t = 0 , 0 , 0.2
while start < distance:
if start < faster_distance:
a = 1.5
else :
a = - 3
move = v0 * t + 1 / 2 * a * t * t
v = v0 + a * t
v0 = v
start += move
trace. append( round ( move) )
return trace
def move_to_gap ( trace) :
slider = wait. until( EC. presence_of_element_located( ( By. CLASS_NAME, 'gt_slider_knob' ) ) )
ActionChains( browser) . click_and_hold( slider) . perform( )
for x in trace:
ActionChains( browser) . move_by_offset( xoffset= x, yoffset= 0 ) . perform( )
sleep( 0.5 )
ActionChains( browser) . release( ) . perform( )
最后的主程序,get_trace(distance-10)这里可以不减10,也可以减别的数值。
def main ( ) :
init( )
login( )
bg, bg_position = get_image_info( 'bg' )
fullbg, fullbg_position = get_image_info( 'fullbg' )
bg_first_line_img, bg_second_line_img = Corp( bg, bg_position)
fullbg_first_line_img, fullbg_second_line_img = Corp( fullbg, fullbg_position)
bg_image = put_imgs_together( bg_first_line_img, bg_second_line_img, 'bg.jpg' )
fullbg_image = put_imgs_together( fullbg_first_line_img, fullbg_second_line_img, 'fullbg.jpg' )
distance = get_distance( bg_image, fullbg_image)
trace = get_trace( distance- 10 )
move_to_gap( trace)
sleep( 5 )
if __name__ == '__main__' :
main( )