1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245
| import time from io import BytesIO from PIL import Image from selenium.common.exceptions import TimeoutException from selenium.webdriver import ActionChains from selenium.webdriver.common.by import By from selenium.webdriver.support.ui import WebDriverWait from selenium.webdriver.support import expected_conditions as EC from os import listdir from os.path import abspath, dirname from selenium import webdriver
TEMPLATES_FOULDER = dirname(abspath(__file__)) + '/templates/' ABSPATH = abspath(r"C:\Program Files (x86)\Google\Chrome\Application\chromedriver.exe")
class WeiboCookies(): def __init__(self, username,password, browser): self.url = 'https://passport.weibo.cn/signin/login?entry=mweibo&r=https://m.weibo.cn/' self.browser = browser self.wait = WebDriverWait(self.browser, 20) self.username = username self.password = password
def open(self): """ 打开网页输入用户名和密码并点击 :return: None """
self.browser.delete_all_cookies() self.browser.get(self.url) username = self.wait.until(EC.presence_of_element_located( (By.ID, 'loginName'))) password = self.wait.until(EC.presence_of_element_located( (By.ID, 'loginPassword'))) submit = self.wait.until(EC.element_to_be_clickable( (By.ID, 'loginAction'))) username.send_keys(self.username) password.send_keys(self.password) time.sleep(2) submit.click()
def password_error(self): """ 判断密码是否错误 :return: """
try: return WebDriverWait(self.browser, 5).until( EC.text_to_be_present_in_element((By.ID, 'errorMsg'), '用户名或密码错误')) except TimeoutException: return False
def login_successfully(self): """ 判断是否登录成功 :return: """
try: return bool( WebDriverWait(self.browser, 5).until(EC.presence_of_element_located( (By.CLASS_NAME, 'drop-title'))) ) except TimeoutException: return False
def get_position(self): """ 获取验证码位置 :return: 验证码位置元组 """ try: img = self.wait.until(EC.presence_of_element_located( (By.CLASS_NAME, 'patt-shadow'))) except TimeoutException: print('未出现验证码') self.open() time.sleep(2) location = img.location size = img.size top, bottom, left, right = location['y'], location['y']+size['height'], location['x'], location['x']+size['width'] return (top, bottom, left, right)
def get_screenshot(self): """ 获取网页截图 :return: 截图对象 """ screenshot = self.browser.get_screenshot_as_png() screenshot = Image.open(BytesIO(screenshot)) return screenshot
def get_image(self, name='captcha.png'): """ 获取验证码图片 :return: 图片对象 """ top, bottom, left, right = self.get_position() print('验证码位置:', top, bottom, left, right) screenshot = self.get_screenshot()
captcha = screenshot.crop((left, top, right, bottom)) return captcha
def is_pixel_equal(self, image1, image2, x, y): """ 判断两个像素是否相同 :param: image1: 图片1 :param: image2: 图片2 :param: x: 位置 x :param: y: 位置 y :return: 像素是否相同 """ pixel1 = image1.load()[x,y] pixel2 = image2.load()[x,y] threshold = 20 if abs(pixel1[0] - pixel2[0]) < threshold and abs(pixel1[1] - pixel2[2]) < threshold and abs(pixel1[2] - pixel2[2]) < threshold: return True else: return False
def same_image(self, image, template):
""" 识别相似验证码 :param image: 待识别验证码 :param template: 模板 :return: """ threshold = 0.99 count = 0 for x in range(image.width): for y in range(image.height): if self.is_pixel_equal(image,template,x,y): count += 1 result = float(count) / (image.height * image.width) if result > threshold: print('匹配成功') return True return False
def detect_image(self, image): """ 匹配图片 :param image: 图片 :return: 拖动顺序 """ for template_name in listdir(TEMPLATES_FOULDER): print('正在匹配:', template_name) template = Image.open(TEMPLATES_FOULDER + template_name) if self.same_image(image,template): numbers = [int(number) for number in list(template_name.split('.')[0])] print('拖动顺序,', numbers) return numbers
def move(self, numbers): """ 根据顺序拖动 :param numbers: :return: """ try: circles = self.browser.find_elements_by_css_selector('.patt-wrap .patt-circ') dx = dy = 0 for index in range(4): circle = circles[numbers[index] - 1] if index == 0: ActionChains(self.browser) \ .move_to_element_with_offset(circle, circle.size['width'] / 2, circle.size['height'] / 2) \ .click_and_hold().perform() else: times = 30 for i in range(times): ActionChains(self.browser).move_by_offset(dx / times, dy / times).perform() time.sleep(1 / times) if index == 3: ActionChains(self.browser).release().perform() else: dx = circles[numbers[index + 1] - 1].location['x'] - circle.location['x'] dy = circles[numbers[index + 1] - 1].location['y'] - circle.location['y'] except: return False
def get_cookies(self): """ 获取Cookies :return: """ return self.browser.get_cookies()
def main(self): """ 破解入口 :return: """ self.open() if self.password_error(): return{ 'status': 2, 'content': '用户名或密码错误' } if self.login_successfully(): cookies = self.get_cookies() return{ 'status': 1, 'content': cookies } image = self.get_image('captcha.png') numbers = self.detect_image(image) self.move(numbers) if self.login_successfully(): cookies = self.get_cookies() return{ 'status': 1, 'content': cookies } else: return{ 'status': 3, 'content': '登录失败' } if __name__ == '__main__': br = webdriver.Chrome(executable_path=ABSPATH) result = WeiboCookies('13480729500', 'fegg', br).main() print(result)
|