python解决12306登录验证码的实现
在家无聊,线代和高数看不懂,整点事情干,就准备预定回学校的高铁票,于是就有了这个文章
准备工作
1.pip安装chromediver,当然也可以手动解压(网上的教程好像没有提到pip,手动安装到c盘pycharm里面的scripts就行了)
这是chromedriver文件官网,在chrome里面设置查看自己的版本,然后找对应的版本就完了
2.注册个超级鹰,,挺厉害的打码平台,微信公众号绑定一下账号给1000积分,足够干12306验证码了
开始实战讲解
1.选择chrome打开12306然后切换到账号登录
默认是扫码登录
f12然后点击账号登录
3.复制xpath,/html/body/div[2]/div[2]/ul/li[2]/a
代码实现
from selenium.webdriver import chrome web = chrome() web.get('https://kyfw.12306.cn/otn/resources/login.html') time.sleep(3) web.find_element_by_xpath('/html/body/div[2]/div[2]/ul/li[2]/a').click()
2.下载验证码(截屏也可以)然后发送给超级鹰
超级鹰官网有个官方文档,下载然后pychram打开,其实就很简单,然后把账号密码改成你自己的,
from chaojiying import chaojiying_client
验证码需要时间加载,所以要sleep(3)就够了,
3.拿到坐标然后模拟点击
好像这个官方叫什么偏移量,挺高大上的,说白了就是建立一个坐标系,给个x,y然后点击就完了,默认左上方是原点
for pre_location in location_list: #切割出来x,y坐标 location = pre_location.split(',') x = int(location[0]) y = int(location[1]) actionchains(web).move_to_element_with_offset(img,x,y).click().perform()
4.登录以后有个滑动验证
现在我还没有找到方法控制滑动速度,匀速运动,但是12306并没有因为这个验证失败
actionchains(web).drag_and_drop_by_offset(button,340,0).perform()
button是那个滑块的xpath,我记得好像是长度330,340肯定是够用了,那个0就是竖y的方向上的滑动
12306靠webdriver判断是不是爬虫
刚开始12306图片和滑动验证通过以后一直说验证失败,百思不得其解,百度发现是因为这个
这是正常页面下的,也就是我改了以后的,加一个这个代码,欺骗一下
def trick_not_chromedriver(): option = options() option.add_argument('--disable-blink-features=automationcontrolled') return option
这个要调用在前面,靠后一点就不行了
全部代码
from selenium.webdriver import chrome import requests,time from hashlib import md5 from selenium.webdriver.common.action_chains import actionchains from selenium.webdriver.chrome.options import options class chaojiying_client(object): def __init__(self, username, password, soft_id): self.username = username password = password.encode('utf8') self.password = md5(password).hexdigest() self.soft_id = soft_id self.base_params = { 'user': self.username, 'pass2': self.password, 'softid': self.soft_id, } self.headers = { 'connection': 'keep-alive', 'user-agent': 'mozilla/4.0 (compatible; msie 8.0; windows nt 5.1; trident/4.0)', } def postpic(self, im, codetype): """ im: 图片字节 codetype: 题目类型 参考 http://www.chaojiying.com/price.html """ params = { 'codetype': codetype, } params.update(self.base_params) files = {'userfile': ('ccc.jpg', im)} r = requests.post('http://upload.chaojiying.net/upload/processing.php', data=params, files=files, headers=self.headers) return r.json() def reporterror(self, im_id): """ im_id:报错题目的图片id """ params = { 'id': im_id, } params.update(self.base_params) r = requests.post('http://upload.chaojiying.net/upload/reporterror.php', data=params, headers=self.headers) return r.json() #获取验证码 def get_verify_img(web): web.find_element_by_xpath('/html/body/div[2]/div[2]/ul/li[2]/a').click() time.sleep(5) verify_img = web.find_element_by_xpath('//*[@id="j-loginimg"]') return verify_img #识别验证码返回坐标 def discern_verify_img(verify_img): chaojiying = chaojiying_client('超级鹰账号', '密码', '软件id') responce = chaojiying.postpic(verify_img.screenshot_as_png, 9004) pre_location = responce['pic_str'] location_list = pre_location.split("|") # 把split写错了,卡了半天 # type_pre_location = type(pre_location) return location_list # return type_pre_location #拿到坐标模拟点击 def click_and_enter(web,location_list,img): for pre_location in location_list: #切割出来x,y坐标 location = pre_location.split(',') x = int(location[0]) y = int(location[1]) actionchains(web).move_to_element_with_offset(img,x,y).click().perform() def enter(web): # input() web.find_element_by_xpath('//*[@id="j-username"]').send_keys('账号') web.find_element_by_xpath('//*[@id="j-password"]').send_keys('密码') web.find_element_by_xpath('//*[@id="j-login"]').click() #滑动验证 def move_verify(web): button = web.find_element_by_xpath('//*[@id="nc_1__scale_text"]/span') actionchains(web).drag_and_drop_by_offset(button,340,0).perform() # 骗12306这不是chromedriver def trick_not_chromedriver(): option = options() option.add_argument('--disable-blink-features=automationcontrolled') return option #现在有一个疫情防控的确认按钮,点一下这个 def yqfk(web): web.get('https://kyfw.12306.cn/otn/leftticket/init') time.sleep(1) web.find_element_by_xpath('//*[@id="qd_closedefaultwarningwindowdialog_id"]').click() #进入查询界面,思路正则表达式,不可信 def get_stick_text(web): web.get('https://kyfw.12306.cn/otn/leftticket/query?leftticketdto.train_date=2021-04-16&leftticketdto.from_station=tnv&leftticketdto.to_station=czf&purpose_codes=0x00') response = web.find_element_by_xpath('/html/body/pre').text return (response) #父子节点一个一个找,显示余票 if __name__ == '__main__': web = chrome(options=trick_not_chromedriver()) web.get('https://kyfw.12306.cn/otn/resources/login.html') time.sleep(5) # click_and_enter(discern_verify_img(get_verify_img())) img = get_verify_img(web) click_and_enter(web,discern_verify_img(img),img) time.sleep(5) enter(web) time.sleep(5) move_verify(web) time.sleep(1) yqfk(web) time.sleep(2) get_verify_img(web)
已经可以登录的,结果就是这个界面
还有一个想法是余票检测,在搞了,应该快了
到此这篇关于python解决12306登录验证码的实现的文章就介绍到这了,更多相关python 12306登录验证码 内容请搜索以前的文章或继续浏览下面的相关文章希望大家以后多多支持!
上一篇: node.js如何操作MySQL数据库