├── README.md └── Demo.py /README.md: -------------------------------------------------------------------------------- 1 | 极验验证码简单破解 2 | -------------------------------------------------------------------------------- /Demo.py: -------------------------------------------------------------------------------- 1 | #! python3 2 | # coding:utf-8 3 | 4 | import time,random 5 | from PIL import Image 6 | from selenium import webdriver 7 | from selenium.webdriver.common.action_chains import ActionChains 8 | import logging 9 | 10 | logging.basicConfig(level=logging.DEBUG, format='%(asctime)s - %(levelname)s -%(message)s') 11 | 12 | phoneNum = '13456788765' 13 | # initial offset 14 | initial_offset = 10 15 | URLs = ['https://biaodan.info/q/7sisis'] 16 | 17 | #TODO get html elements 18 | def sendPhone(driver, phoneNum, phoneInputClass, sendPhoneButtonId): 19 | # driver = webdriver.Chrome() 20 | logging.debug('Send Phone Start') 21 | phoneInput = driver.find_element_by_class_name(phoneInputClass) 22 | phoneInput.send_keys(phoneNum) 23 | time.sleep(2) 24 | sendBtn = driver.find_element_by_id(sendPhoneButtonId) 25 | sendBtn.click() 26 | time.sleep(5) 27 | 28 | #TODO compare Captcha & return tarck 29 | def elementsScreenshot(driver, bgImgClass, dragBallClass): 30 | # driver = webdriver.Chrome() 31 | logging.debug('start make background screenshot') 32 | driver.find_element_by_class_name(bgImgClass).screenshot('bg_full.png') 33 | time.sleep(2) 34 | ball = driver.find_element_by_class_name(dragBallClass) 35 | ActionChains(driver).click_and_hold(ball).perform() 36 | ActionChains(driver).move_by_offset(190, 0).perform() 37 | # move the ball to right 38 | # this is important 39 | time.sleep(0.5) 40 | driver.find_element_by_class_name(bgImgClass).screenshot('cut.png') 41 | # move the ball to left 42 | ActionChains(driver).move_by_offset(-30, 0).perform() 43 | time.sleep(1) 44 | ActionChains(driver).move_by_offset(-50, 0).perform() 45 | time.sleep(1) 46 | ActionChains(driver).move_by_offset(-40, 0).perform() 47 | time.sleep(1) 48 | ActionChains(driver).move_by_offset(-30, 0).perform() 49 | time.sleep(1) 50 | ActionChains(driver).move_by_offset(-40, 0).perform() 51 | 52 | def dragBall(driver, track, dragBallClass): 53 | ball = driver.find_element_by_class_name(dragBallClass) 54 | logging.debug('ball start move') 55 | # simulate human's behave 56 | while track: 57 | len = random.choice(track) 58 | ActionChains(driver).move_by_offset(len, 0).perform() 59 | track.remove(len) 60 | logging.debug(track) 61 | time.sleep(len/10) 62 | imitate2L = ActionChains(driver).move_by_offset(-2, 0) 63 | imitateL = ActionChains(driver).move_by_offset(-1, 0) 64 | time.sleep(0.015) 65 | imitate2L.perform() 66 | time.sleep(0.04) 67 | imitateL.perform() 68 | time.sleep(0.04) 69 | imitate2L.perform() 70 | time.sleep(0.04) 71 | imitateL.perform() 72 | time.sleep(0.04) 73 | imitate2L.perform() 74 | ActionChains(driver).pause(random.randint(6, 10) / 10).release(ball).perform() 75 | 76 | def getTrack(distance): 77 | logging.debug('calcute distance track') 78 | # simulate human's hebace s = 1 / 2 a t t 79 | track =[] 80 | current = 0 81 | mid = distance * 3 / 4 82 | t = random.randint(2, 3) / 10 83 | v = 0 84 | logging.debug('1') 85 | while current < distance: 86 | if current < mid: 87 | a = 2 88 | else: 89 | a = -3 90 | v0 = v 91 | v = v0 + a * t 92 | move = v0 * t + 1 / 2 * a * t * t 93 | current += move 94 | track.append(round(move)) 95 | logging.debug(track) 96 | return track 97 | 98 | # TODO compare two img 99 | def compareImg(img1, img2, x, y): 100 | logging.debug('compare img start') 101 | pix1 = img1.load()[x, y] 102 | pix2 = img2.load()[x, y] 103 | threshold = 60 104 | if (abs(pix1[0] - pix2[0] < threshold) and abs(pix1[1] - pix2[1] < threshold) and abs(pix1[2] - pix2[2] < threshold)): 105 | return True 106 | else: 107 | return False 108 | 109 | def getOffset(bgFullPath, bgPath): 110 | logging.debug('get img offset') 111 | bg_full = Image.open(bgFullPath) 112 | bg = Image.open(bgPath) 113 | left = initial_offset 114 | for width in range(left, bg_full.size[0]): 115 | for height in range(bg_full.size[1]): 116 | if not compareImg(bg_full, bg, width, height): 117 | left = width 118 | return left 119 | return left 120 | #TODO execute Crack it 121 | 122 | def main(driver): 123 | logging.debug('main() start') 124 | for url in URLs: 125 | driver.get(url) 126 | logging.debug('%s get html', url) 127 | time.sleep(3) 128 | sendPhone(driver, phoneNum, 'filter-input', 'btnSendCode') 129 | elementsScreenshot(driver, 'gt_cut_fullbg', 'gt_slider_knob') 130 | distance = getOffset('bg_full.png', 'cut.png') 131 | # logging.debug('%s',distance) 132 | track = getTrack(distance) 133 | dragBall(driver, track, 'gt_slider_knob') 134 | time.sleep(3) 135 | 136 | if __name__ == '__main__': 137 | driver = webdriver.Chrome() 138 | for i in range(1, 2): 139 | logging.debug('%s Test', i) 140 | try: 141 | main(driver) 142 | except: 143 | print("%d Error", i) 144 | pass 145 | driver.close() 146 | driver.quit() 147 | 148 | --------------------------------------------------------------------------------