一、126,163邮箱模拟登陆
1 # -*- coding:utf-8 -*- 2 import time 3 from selenium import webdriver 4 def login126_or_163emall(url): 5 login_name = input("请输入账号:") 6 login_password = input("请输入密码:") 7 8 # 打开自动测试软件Chrome 9 driver = webdriver.Chrome(executable_path="D:chromedriver.exe") 10 11 # 模拟窗口最大化 12 driver.maximize_window() 13 14 # 打开目标网站 15 driver.get(url=url) 16 time.sleep(10) 17 18 # 切换为密码登录 19 password_login_button = driver.find_element_by_id("lbNormal") 20 password_login_button.click() 21 22 # 由于126邮箱是iframe嵌套,所以要切换到iframe窗口 23 elem = driver.find_element_by_css_selector("iframe[id^='x-URS-iframe']") 24 25 # 用frame的index来定位,定位iframe窗口 26 driver.switch_to.frame(elem) 27 28 # 定位到账号输入框,不需要输入@126.com 29 user_name = driver.find_element_by_name("email") 30 user_name.send_keys(login_name) 31 32 # 定位到密码输入框 33 user_password = driver.find_element_by_name("password") 34 user_password.send_keys(login_password) 35 time.sleep(3) 36 37 # 定位到登录按钮 38 login_button = driver.find_element_by_id("dologin") 39 login_button.click() 40 time.sleep(5) 41 42 # 获取用户登录的cookies,返回一个字典 43 cookies = driver.get_cookies()[0] 44 print(cookies) 45 time.sleep(10) 46 47 # 关闭模拟浏览器窗口 48 driver.close() 49 50 if __name__ == '__main__': 51 # url = "https://mail.126.com/" # 126邮箱url 52 url = "https://mail.163.com/" # 163邮箱url 53 login126_or_163emall(url=url)
输出的cookies如下:
""" {'domain': '.163.com', 'expiry': 4717308714, 'httpOnly': False, 'name': '_ntes_nnid', 'path': '/', 'secure': False, 'value': 'cf36cf83b0562fccb3ab872f3b1dfa4c,1563708714807'} """
二、哔哩哔哩模拟登陆
1 import time 2 import random 3 from PIL import Image 4 from io import BytesIO 5 from selenium import webdriver 6 from selenium.webdriver.common.by import By 7 from selenium.webdriver import ActionChains 8 from selenium.webdriver.support.wait import WebDriverWait 9 from selenium.webdriver.support import expected_conditions as EC 10 11 border = 6 # 滑块左边框到验证图片左边框的距离 12 13 class CrackGeetest(): 14 def __init__(self): 15 self.url = 'https://passport.bilibili.com/login' 16 self.browser = webdriver.Chrome(r"D:chromedriver.exe") 17 18 # 设置浏览器为最大窗口 19 self.browser.maximize_window() 20 self.wait = WebDriverWait(self.browser,timeout=5) 21 22 def close(self): 23 self.browser.close() # 关闭浏览器 24 self.browser.quit() # 退出并停止执行chromedriver.exe 25 26 27 # 获取带缺口的图片 28 def get_geetest_image(self, name='captcha.png'): 29 30 # 获取完整的验证图片 31 img = self.wait.until(EC.presence_of_element_located((By.XPATH, '/html/body/div[2]/div[2]/div[6]/div/div[1]/div[1]/div/a/div[1]'))) 32 time.sleep(2) 33 location = img.location # 获取元素位置 34 size = img.size # 获取元素尺寸 35 print(location,size) 36 37 top = location['y'] 38 bottom = location['y'] + size['height'] 39 left = location['x'] 40 right = location['x'] + size['width'] 41 print('验证码位置', top, bottom, left, right) 42 43 # 获取当前窗口的屏幕截图(二进制数据) 44 screenshot = self.browser.get_screenshot_as_png() 45 46 # 使用BytesIO对象在内存中读写bytes(就是读取截图) 47 screenshot = Image.open(BytesIO(screenshot)) 48 screenshot.save(r"D:photoimagescreenshot.png" ) 49 50 # 按照图片验证码的大小尺寸进行剪切 51 captcha = screenshot.crop((left, top, right, bottom)) 52 53 # 将图片验证码保存到指定路径 54 captcha.save(r"D:photoimage\%s"%name) 55 return captcha 56 57 58 # 获取缺口位置 59 def get_gap(self, img1, img2): 60 left = 60 # 滑块的宽度+滑块左边框到验证图片左边框的距离 61 for i in range(left, img1.size[0]): # 遍历不带缺口的图片img1的RGB像素点 62 for j in range(img1.size[1]): 63 if not self.is_pixel_equal(img1, img2, i, j): # 判断两张图片同一位置的像素点是否相等 64 left = i 65 return left 66 return left 67 68 69 # 判断两张验证图片同一位置的像素点是否相同 70 def is_pixel_equal(self, img1, img2, x, y): 71 72 # 取两个图片的像素点 73 pix1 = img1.load()[x,y] 74 pix2 = img2.load()[x,y] 75 threshold = 60 # 阈值 76 pix_r = abs(pix1[0] - pix2[0]) # R 77 pix_g = abs(pix1[1] - pix2[1]) # G 78 pix_b = abs(pix1[2] - pix2[2]) # B 79 if (pix_r < threshold) and (pix_g < threshold) and (pix_b < threshold): 80 return True 81 else: 82 return False 83 84 # 获取移动轨迹 85 def get_track(self, distance): 86 track = [] # 移动轨迹 87 current = 0 # 当前位移 88 mid = distance * 3 / 4 # 减速阈值 89 t = random.randint(2,3)/10 # 计算间隔 90 v = 0 # 初速度 91 distance += 5 92 while current < distance: # 判断当前位移是否小于缺口距离 93 if current < mid: # 如果当前位移小于减速的阈值 94 a = 2 # 则加速度为正 95 else: 96 a = -3 # 否则加速度为负 97 v0 = v # 初速度v0 98 v = v0 + a * t # 当前速度v (v = v0 + at) 99 x = v0*t + 1/2*a*t*t # 移动距离x (x = v0t + 0.5at^2) 100 current += x # 当前位移 101 track.append(round(x)) # 加入轨迹(round为四舍五入) 102 return track 103 104 105 # 移动缺口滑块 106 def move_to_gap(self, slider, tracks): 107 """ 108 :param slider: 滑块 109 :param tracks: 移动轨迹 110 """ 111 random.shuffle(tracks) 112 113 # 创建一个鼠标移动的动作链,在滑块上按住的鼠标左键,并执行。 114 ActionChains(self.browser).click_and_hold(slider).perform() 115 116 # 正向移动轨迹 117 for x in tracks: 118 # 创建一个鼠标移动的动作链,将鼠标移动到当前鼠标位置的偏移位置(x,0)上,并执行。 119 ActionChains(self.browser).move_by_offset(xoffset=x, yoffset=0).perform() 120 121 # 模拟人工滑动超过缺口位置返回至缺口的情况,同时还加入了随机数,都是为了更贴近人工滑动轨迹 122 action = ActionChains(self.browser).move_by_offset(xoffset=-1, yoffset=0) 123 time.sleep(0.015) 124 action.perform() 125 time.sleep(random.randint(6, 10) / 10) 126 action.perform() 127 time.sleep(0.04) 128 action.perform() 129 time.sleep(random.randint(6, 10) / 10) 130 action.perform() 131 time.sleep(0.019) 132 action.perform() 133 time.sleep(random.randint(6, 10) / 10) 134 ActionChains(self.browser).move_by_offset(xoffset=1, yoffset=0).perform() 135 136 # 模拟抖动(由于释放鼠标是会产生抖动) 137 ActionChains(self.browser).move_by_offset(xoffset=-3, yoffset=0).perform() 138 ActionChains(self.browser).move_by_offset(xoffset=2, yoffset=0).perform() 139 140 time.sleep(0.5) 141 # 创建一个鼠标行为的动作链,释放滑块上的鼠标按钮,并执行。 142 ActionChains(self.browser).release().perform() 143 144 def crack(self): 145 try: 146 # 打开网页 147 self.browser.get(self.url) 148 # 获取用户名输入框 149 emall = self.wait.until(EC.presence_of_all_elements_located((By.XPATH,'//*[@id="login-username"]')))[0] 150 151 # 获取密码输入框 152 password = self.wait.until(EC.presence_of_all_elements_located((By.XPATH,'//*[@id="login-passwd"]')))[0] 153 154 # 发送用户名 155 emall.send_keys("15612345678") 156 157 # 发送密码 158 password.send_keys("1234567890") 159 160 # 点击登录按钮使之显示验证图片 161 loginbutton = self.wait.until(EC.element_to_be_clickable((By.XPATH, '//*[@id="geetest-wrap"]/ul/li[5]/a[1]'))) 162 loginbutton.click() 163 164 # 确认验证图片加载完成(获取完整的验证码div) 165 self.wait.until(EC.presence_of_element_located((By.XPATH, '/html/body/div[2]/div[2]/div[6]/div'))) 166 167 # 获取移动滑块(slider:滑块) 168 slider = self.wait.until(EC.element_to_be_clickable((By.XPATH, '/html/body/div[2]/div[2]/div[6]/div/div[1]/div[2]/div[2]'))) 169 170 # 获取带缺口的验证码图片(完整的验证图片) 171 image1 = self.get_geetest_image('captcha1.png') 172 173 #========= 在当前窗口执行JavaScript语句(由于验证码原图被切分成搞多块)=========# 174 # 组合验证码方法一: 175 element = self.wait.until(EC.presence_of_element_located((By.CSS_SELECTOR, 'canvas.geetest_canvas_fullbg.geetest_fade.geetest_absolute'))) 176 self.browser.execute_script("arguments[0].style=arguments[1]",element,"display: block;") 177 178 # 组合验证码方法二:(本人建议使用此方法) 179 # self.browser.execute_script('document.querySelectorAll("canvas")[2].style=""') # 获取缺块儿验证码 180 # self.browser.execute_script('document.querySelectorAll("canvas")[3].style=""') # 获取完整的验证码 181 182 # 获取带缺口的验证码图片(不完整的验证图片) 183 image2 = self.get_geetest_image('captcha2.png') 184 185 # 调用获取缺口位置函数(滑块的位置) 186 gap = self.get_gap(image1, image2) 187 188 # 减点滑块左边框到验证图片左边框的距离 189 gap -= border 190 print('滑块的位置', gap) 191 192 # 调用获取移动轨迹函数(track:移动轨迹) 193 track = self.get_track(gap) 194 195 # 调用移动缺口滑块函数进行滑动 196 self.move_to_gap(slider, track) 197 time.sleep(1) 198 # 获取验证完成后返回的数据“验证成功” 199 success = self.wait.until(EC.text_to_be_present_in_element((By.XPATH, '/html/body/div[2]/div[2]/div[3]/div[2]'), '验证成功')) 200 print(success) 201 time.sleep(5) 202 203 # 关闭浏览器 204 self.close() 205 except: 206 print('Failed-Retry') # 失败重试 207 self.crack() 208 209 if __name__ == '__main__': 210 crack = CrackGeetest() 211 crack.crack()
由于哔哩哔哩验证码是极验的滑动验证码,验证码图片是由很多个小块图片碎片组合而成,所以解决办法如下:
#========= 在当前窗口执行JavaScript语句(由于验证码原图被切分成搞多块)=========# # 组合验证码方法一: element = self.wait.until(EC.presence_of_element_located((By.CSS_SELECTOR, 'canvas.geetest_canvas_fullbg.geetest_fade.geetest_absolute'))) self.browser.execute_script("arguments[0].style=arguments[1]",element,"display: block;") # 组合验证码方法二:(本人建议使用此方法) # self.browser.execute_script('document.querySelectorAll("canvas")[2].style=""') # 获取缺块儿验证码 # self.browser.execute_script('document.querySelectorAll("canvas")[3].style=""') # 获取完整的验证码