├── README.md └── main.py /README.md: -------------------------------------------------------------------------------- 1 | # 抖音登录自动化 2 | Python + Selenium+openCV 破解抖音登录滑块验证码 3 | 暑假实习做的第一个项目,纪念并分享一下 4 | 这项目还能再优化下,像爬取url可以多线程等等,不过因为效益不高,所以就不继续优化了 5 | -------------------------------------------------------------------------------- /main.py: -------------------------------------------------------------------------------- 1 | from selenium import webdriver 2 | from selenium.webdriver.common.action_chains import ActionChains 3 | import selenium 4 | import cv2 5 | import requests 6 | import time 7 | from selenium.webdriver.support.ui import WebDriverWait 8 | from selenium.webdriver.remote.webelement import WebElement 9 | from selenium.webdriver.common.by import By 10 | from PIL import Image 11 | from selenium.webdriver.chrome.options import Options #(这个需要前提引入的,就想时间等待一样) 12 | from selenium.webdriver.support import expected_conditions as ec 13 | from selenium.webdriver.support.ui import WebDriverWait 14 | import random 15 | 16 | 17 | options = webdriver.ChromeOptions() 18 | wb = webdriver.Chrome(options=options) 19 | 20 | #放检验的打开浏览器 21 | # opt = Options() 22 | # opt.add_experimental_option('excludeSwitches',['enable-automation']) 23 | # wb = webdriver.Chrome(options=opt) 24 | 25 | #运行正在打开的浏览器 26 | # opt = Options() 27 | # opt.add_experimental_option('debuggerAddress','127.0.0.1:9527') 28 | # wb = webdriver.Chrome(options=opt) 29 | 30 | #打开无头浏览器 31 | # chrome_options = Options() 32 | # chrome_options.add_argument('--headless') 33 | # wb = webdriver.Chrome(options=chrome_options) 34 | 35 | time_start = time.time()#开始计时 36 | def get_url(): 37 | wb.get('https://www.douyin.com/discover') 38 | WebDriverWait(wb, 5, 0.5).until(ec.visibility_of_element_located( 39 | (By.XPATH, '//*[@id="login-pannel"]/div[3]/div/article/article/article/div[1]/ul[1]/li[2]')),'失败')#等待 直到登录按钮出现 40 | # time.sleep(1) 41 | try: 42 | wb.find_element(By.XPATH,'//*[@id="login-pannel"]/div[3]/div/article/article/article/div[1]/ul[1]/li[2]').click() 43 | except: 44 | print(WebDriverWait(wb, 2, 0.5).until(ec.visibility_of_element_located( 45 | (By.XPATH, '//*[@id="verify-bar-close"]')), '失败'))#关闭点选验证界面 46 | 47 | # time.sleep(1.5) 48 | wb.find_element(By.XPATH, '//*[@id="verify-bar-close"]').click() 49 | print(WebDriverWait(wb, 2, 0.5).until(ec.visibility_of_element_located( 50 | (By.XPATH, '//*[@id="verify-bar-close"]')), '失败'))#等待 直到点选验证界面出现 51 | # time.sleep(1) 52 | wb.find_element(By.XPATH, '//*[@id="verify-bar-close"]').click() 53 | # time.sleep(0.5) 54 | WebDriverWait(wb, 2, 0.5).until(ec.visibility_of_element_located( 55 | (By.XPATH, '//*[@id="login-pannel"]/div[3]/div/article/article/article/div[1]/ul[1]/li[2]')), '失败') 56 | wb.find_element(By.XPATH,'//*[@id="login-pannel"]/div[3]/div/article/article/article/div[1]/ul[1]/li[2]').click() 57 | pass 58 | 59 | time.sleep(1) 60 | try: #要输入就要下面这三行 61 | wb.find_element(By.XPATH, '//*[@id="login-pannel"]/div[3]/div/article/article/article/form/div[1]/div/input').click() 62 | wb.find_element(By.XPATH, '//*[@id="login-pannel"]/div[3]/div/article/article/article/form/div[1]/div/input').clear() 63 | wb.find_element(By.XPATH, '//*[@id="login-pannel"]/div[3]/div/article/article/article/form/div[1]/div/input').send_keys(18948233333) 64 | except: #预防点选验证码弹出 65 | # time.sleep(2) 66 | print(WebDriverWait(wb, 2, 0.5).until(ec.visibility_of_element_located( 67 | (By.XPATH, '//*[@id="verify-bar-close"]')), '失败')) # 等待 直到点选验证界面出现 68 | wb.find_element(By.XPATH, '//*[@id="verify-bar-close"]').click() 69 | time.sleep(1) 70 | wb.find_element(By.XPATH, '//*[@id="verify-bar-close"]').click() 71 | time.sleep(0.5) 72 | wb.find_element(By.XPATH, '//*[@id="login-pannel"]/div[3]/div/article/article/article/form/div[1]/div/input').click() 73 | wb.find_element(By.XPATH, '//*[@id="login-pannel"]/div[3]/div/article/article/article/form/div[1]/div/input').clear() 74 | wb.find_element(By.XPATH, '//*[@id="login-pannel"]/div[3]/div/article/article/article/form/div[1]/div/input').send_keys(18948233333) 75 | pass 76 | # wb.find_element(By.XPATH, '/html/body/div[3]/div/div[2]/div[3]/div[2]/div[2]/div[1]/input').send_keys(122) 77 | time.sleep(0.5) 78 | wb.find_element(By.XPATH, '//*[@id="login-pannel"]/div[3]/div/article/article/article/form/div[2]/div/span').click() #点击获取验证码 79 | # time.sleep(1) 80 | 81 | time_end1 = time.time() # 结束计时 82 | time_c1 = time_end1 - time_start # 运行所花时间 83 | print('time cost', time_c1, 's') 84 | return 85 | 86 | def verify(): 87 | #保存验证码 88 | verify_img = wb.find_element(By.XPATH, '//*[@id="captcha-verify-image"]')#读取要拼图的图片 89 | point_img = wb.find_element(By.XPATH,'//*[@id="captcha_container"]/div/div[2]/img[2]')#读取拼图的图片 90 | img_url = verify_img.get_attribute('src') 91 | img_url2 = point_img.get_attribute('src') 92 | print('成功获取图片url') 93 | time.sleep(0.5) 94 | content = requests.get(img_url).content 95 | content2 = requests.get(img_url2).content 96 | print('成功写入content') 97 | with open('verift_img.jpg','wb')as f:#要写入本地 98 | f.write(content) 99 | verify_img = cv2.imread('verift_img.jpg') 100 | with open('point_img.jpg','wb')as f: 101 | f.write(content2) 102 | point_img = cv2.imread('point_img.jpg')#变成BRG格式来OpenCV处理 103 | 104 | bg_edge = cv2.Canny(verify_img, 100, 200)#获取图像的边缘,Canny(图,阈值,阈值) 105 | tp_edge = cv2.Canny(point_img, 100, 200) 106 | 107 | bg_pic = cv2.cvtColor(bg_edge, cv2.COLOR_GRAY2RGB)#颜色空间转换函数,cvtColor(图,要变成的格式) 108 | tp_pic = cv2.cvtColor(tp_edge, cv2.COLOR_GRAY2RGB) 109 | # 缺口匹配 110 | res = cv2.matchTemplate(bg_pic, tp_pic, cv2.TM_CCOEFF_NORMED)#模板匹配函数,mathTemplate(图,图,匹配类型【一般用cv2.TM_CCOEFF_NORMED】) 111 | min_val, max_val, min_loc, max_loc = cv2.minMaxLoc(res) # 寻找最优匹配 112 | X = max_loc[0]*340/552 #根据图片真实与表面大小的比例进行缩放 113 | ''' 114 | # # 绘制方框 115 | # th, tw = tp_pic.shape[:2] 116 | # tl = max_loc # 左上角点的坐标 117 | # br = (tl[0]+tw,tl[1]+th) # 右下角点的坐标 118 | # cv2.rectangle(verify_img, tl, br, (0, 0, 255), 2) # 绘制矩形 119 | # cv2.imwrite('out.jpg', verify_img) # 保存在本地 120 | ''' 121 | return(X) 122 | 123 | 124 | def check(): 125 | #用于验证码输入,几乎没有用 126 | wb.find_element(By.XPATH, 127 | '//*[@id="login-pannel"]/div[3]/div/article/article/article/form/div[2]/div/div/input').click() 128 | wb.find_element(By.XPATH, 129 | '//*[@id="login-pannel"]/div[3]/div/article/article/article/form/div[2]/div/div/input').clear() 130 | wb.find_element(By.XPATH, 131 | '//*[@id="login-pannel"]/div[3]/div/article/article/article/form/div[2]/div/div/input').send_keys(111111) 132 | return 133 | 134 | # 移动滑块 135 | def start_move(distance): 136 | element = wb.find_element(By.XPATH,('//*[@id="secsdk-captcha-drag-wrapper"]/div[2]')) 137 | # 使用滑块的一半进行偏移设置 138 | # distance -= element.size.get('width') / 2 139 | # distance += 30 140 | 141 | # 按下鼠标左键 142 | ActionChains(wb).click_and_hold(element).perform()#点并按住elemnet,操作 143 | time.sleep(0.5) 144 | while distance > 0: 145 | if distance > 20: 146 | # 如果距离大于20,就让他移动快一点 147 | span = random.randint(60, 70)# 148 | else: 149 | # 快到缺口了,就移动慢一点 150 | span = random.randint(45, 50) 151 | ActionChains(wb).move_by_offset(span, 0).perform() 152 | distance -= span 153 | time.sleep(random.randint(10, 50) / 100) 154 | 155 | ActionChains(wb).move_by_offset(distance, 1).perform() 156 | ActionChains(wb).release(on_element=element).perform() 157 | 158 | 159 | 160 | if __name__ == '__main__': 161 | get_url() 162 | WebDriverWait(wb, 5,0.5).until(ec.visibility_of_element_located((By.XPATH, '//*[@id="captcha-verify-image"]')), '失败') 163 | while ec.visibility_of_element_located((By.XPATH, '//*[@id="captcha-verify-image"]')): 164 | X = verify() 165 | print('图片获取完成') 166 | time.sleep(1) 167 | WebDriverWait(wb, 5, 0.5).until(ec.element_to_be_clickable( 168 | (By.XPATH, '//*[@id="secsdk-captcha-drag-wrapper"]/div[2]')),'失败') 169 | print('开始滑块验证') 170 | start_move(X) 171 | print('滑块验证完成') 172 | time.sleep(1) 173 | # try: 174 | # time.sleep(1) 175 | # check() 176 | # except: 177 | # X = verify() 178 | # start_move(X) 179 | # time.sleep(0.5) 180 | # X = verify() 181 | # start_move(X) 182 | # time.sleep(0.5) 183 | # print('第二次滑块验证完成') 184 | time_end = time.time() # 结束计时 185 | time_c = time_end - time_start # 运行所花时间 186 | print('time cost', time_c, 's') 187 | # 188 | # # wb.get_screenshot_as_file("d:\\bing.png") 189 | # wb.save_screenshot('img0.png') 190 | 191 | 192 | print('****完成啦****') --------------------------------------------------------------------------------