基本方案:
一、获取Bilibili的乱码图片地址,并保存到本地
二、获取图片的坐标
三、根据坐标,将乱码图片进行切割
四、将切割的图片进行重新拼接
五、校验拼接好的原图与缺口图的像数值,得出需要滑动的距离
六、计算滑动轨迹
from time import sleep
from selenium import webdriver
from selenium.webdriver import ActionChains
from selenium.webdriver.common.by import By
from selenium.webdriver.support.wait import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
from PIL import Image
from lxml.html import etree
import re, requests
class BiliBiliSlideCode:
def __init__(self):
self.driver = webdriver.Chrome()
self.wait = WebDriverWait(self.driver, 10)
def _findEle(self, *loc):
try:
self.wait.until(EC.presence_of_element_located(*loc))
return self.driver.find_element(by=loc[0][0], value=loc[0][1])
except:
print("没有找到元素 %s" % loc)
def open(self, user, passw):
self.driver.get('https://passport.bilibili.com/login')
self._findEle((By.ID, 'login-username')).send_keys(user)
self._findEle((By.ID, 'login-passwd')).send_keys(passw)
def get_image(self):
bg_image_path = 'image/bg_messy_code.jpg'
fullbg_image_path = 'image/fullbg_messy_code.jpg'
html = etree.HTML(self.driver.page_source)
fullbg_image_styles = html.xpath("//div[contains(@class,'gt_cut_fullbg gt_show')]//@style")
fullbg_image_url = str(re.findall('url\(\"(.*?)\"\)', fullbg_image_styles[0])[0]).replace('webp', 'jpg')
bg_image_styles = html.xpath("//div[contains(@class,'gt_cut_bg gt_show')]//@style")
bg_image_url = str(re.findall('url\(\"(.*?)\"\)', bg_image_styles[0])[0]).replace('webp', 'jpg')
with open(bg_image_path, 'wb') as f:
bg_image_data = requests.get(bg_image_url).content
f.write(bg_image_data)
with open(fullbg_image_path, 'wb') as f:
fullbg_image_data = requests.get(fullbg_image_url).content
f.write(fullbg_image_data)
bg_messy_code_image = Image.open(bg_image_path)
fullbg_messy_code_image = Image.open(fullbg_image_path)
return bg_messy_code_image, self._potions(bg_image_styles), \
fullbg_messy_code_image, self._potions(fullbg_image_styles)
def _potions(self, image_styles: any):
image_postions = []
for image_style in image_styles:
postion = re.findall('position:(.*?);', image_style)[0]
scope = postion.replace('px', '').strip().split(' ')
image_postions.append([int(scope[0]), int(scope[1])])
return image_postions
def split_image(self, image: Image.Image, potions: [[]]):
first_images = []
second_image = []
for p in potions:
width = abs(p[0])
if p[1] == -58:
box = width, 58, width + 10, 116
first_images.append(image.crop(box))
else:
box = width, 0, width + 10, 58
second_image.append(image.crop(box))
return first_images, second_image
def _joint_image(self, first_images, second_images, filename):
image = Image.new("RGB", (260, 116))
first_i = 0
for first_image in first_images:
print()
image.paste(first_image, (first_i, 0))
first_i += first_image.size[0]
second_i = 0
for second_image in second_images:
image.paste(second_image, (second_i, 58))
second_i += second_image.size[0]
image.save(filename)
def merge_messy_image(self):
bg_image, bg_potions, fullbg_image, fullbg_potions = self.get_image()
bg_first_images, bg_second_images = self.split_image(bg_image, bg_potions)
fullbg_first_images, fullbg_second_images = self.split_image(fullbg_image, fullbg_potions)
self._joint_image(bg_first_images, bg_second_images, 'image/bg_merge_image.jpg')
self._joint_image(fullbg_first_images, fullbg_second_images, 'image/fullbg_merge_image.jpg')
def image_is_same(self, bg_image: Image.Image, fullbg_image: Image.Image, x, y):
bg_pixel = bg_image.getpixel((x, y))
fullbg_pixel = fullbg_image.getpixel((x, y))
for i in range(0, 3):
if abs(bg_pixel[i]) - abs(fullbg_pixel[i]) >= 50:
return False
else:
return True
def count_slide_chunk(self):
bg_image = Image.open('image/bg_merge_image.jpg')
fullbg_image = Image.open('image/fullbg_merge_image.jpg')
for i in range(0,bg_image.size[0]):
for j in range(0,bg_image.size[1]):
if not self.image_is_same(bg_image,fullbg_image,i,j):
return i
def reckon_trail(self):
print('计算运动轨迹')
track = []
distance = self.count_slide_chunk()
distance = int(distance) - 7
print('缺口坐标', distance)
fast_distance = distance * (4 / 5)
start, v0, t = 0, 0, 0.2
while start < distance:
if start < fast_distance:
a = 1.5
else:
a = -3
move = v0 * t + 1 / 2 * a * t * t
print("move : %s" % move)
v = v0 + a * t
print("v : %s" % v)
v0 = v
print("v0 : %s" % v0)
start += move
print("start : %s" % start)
track.append(round(move))
return track
def move_block(self):
print('开始模拟')
track = self.reckon_trail()
slider = self.wait.until(EC.presence_of_element_located((By.CLASS_NAME, 'gt_slider_knob')))
ActionChains(self.driver).click_and_hold(slider).perform()
for x in track:
ActionChains(self.driver).move_by_offset(xoffset=x, yoffset=0).perform()
ActionChains(self.driver).release().perform()
if __name__ == '__main__':
bili_code = BiliBiliSlideCode()
bili_code.open('手机号', '密码')
bili_code.merge_messy_image()
bili_code.move_block()
参考地址: https://blog.csdn.net/thindi/article/details/83152903