from io import BytesIO
from PIL import Image
from selenium import webdriver
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 chaojiying import Chaojiying
from selenium.common.exceptions import TimeoutException
USERNAME = 'w1179380391'
PASSWORD = 'wjh07233'
CHAOJIYING_USERNAME = '1179380391'
CHAOJIYING_PASSWORD = 'wjh07233'
CHAOJIYING_SOFT_ID = '893590'
CHAOJIYING_KIND = '9004'
class CrackTouClick():
def __init__(self): #登陆
self.url = 'https://kyfw.12306.cn/otn/login/init'
self.browser = webdriver.Chrome()
self.wait = WebDriverWait(self.browser, 20)
self.email = USERNAME
self.password = PASSWORD
self.chaojiying = Chaojiying(CHAOJIYING_USERNAME, CHAOJIYING_PASSWORD, CHAOJIYING_SOFT_ID)
def __del__(self): #关闭浏览器
self.browser.close()
def open(self): #输入账号密码
self.browser.get(self.url)
username = self.wait.until(EC.presence_of_element_located((By.CSS_SELECTOR, 'input#username')))
password = self.wait.until(EC.presence_of_element_located((By.CSS_SELECTOR, 'input#password')))
username.send_keys(self.email)
password.send_keys(self.password)
def get_touclick_element(self): #获取验证码位置,网页显示比例为100%的位置
element = self.wait.until(EC.presence_of_element_located((By.CSS_SELECTOR, '.touclick')))
return element
def get_position(self): #获取验证码坐标
element = self.get_touclick_element()
location = element.location
size = element.size
top, bottom, left, right = location['y']*1.25, (location['y'] + size['height'])*1.25, location['x']*1.25, (location['x'] + size['width'])*1.25
return (top, bottom, left, right)
def get_screenshot(self): #截图
screenshot = self.browser.get_screenshot_as_png()
screenshot = Image.open(BytesIO(screenshot))
return screenshot
def get_touclick_image(self, name='12306.png'): #裁剪验证码截图
top, bottom, left, right = self.get_position()
screenshot = self.get_screenshot()
captcha = screenshot.crop((left, top, right, bottom))
captcha.save(name)
return captcha
def get_points(self, captcha_result): #分析超级鹰返回的坐标
groups = captcha_result.get('pic_str').split('|')
locations = [[int(number) for number in group.split(',')] for group in groups] #列表分析
return locations
def touch_click_words(self, locations): #模拟点击
for location in locations:
print(location)
ActionChains(self.browser).move_to_element_with_offset(self.get_touclick_element(), location[0]/1.25,location[1]/1.25).click().perform()
def login(self): #点击登陆按钮
submit = self.wait.until(EC.element_to_be_clickable((By.ID, 'loginSub')))
submit.click()
def crack(self):
self.open()
# 获取验证码图片
image = self.get_touclick_image()
bytes_array = BytesIO()
image.save(bytes_array, format='PNG')
# 识别验证码
result = self.chaojiying.post_pic(bytes_array.getvalue(), CHAOJIYING_KIND)
print(result)
# 解析识别结果
locations = self.get_points(result)
# 进行点击图片
self.touch_click_words(locations)
# 点击登陆
self.login()
# 判断是否出现用户信息
try:
success = self.wait.until(EC.text_to_be_present_in_element((By.CSS_SELECTOR, '.welcome-name'), '王晋浩'))
print(success)
cc = self.browser.find_element(By.CSS_SELECTOR,'.welcome-name')
print(cc.text)
except TimeoutException:
# 如果失败了超级鹰会返回分值
self.chaojiying.report_error(result['pic_id'])
self.crack()
if __name__ == '__main__':
crack = CrackTouClick()
crack.crack()