一、二维码登录方式
二维码登录方式:用户手机端扫描网页二维码登录,比账号密码登录更简易
话不多说,先上代码:
initmyUrl = 'https://kyfw.12306.cn/otn/view/index.html'
script = 'Object.defineProperty(navigator,"webdriver",{get:() => false,});' # 修改navigator属性,避免爬虫被12306发现
def Login(account, password, from_station, to_station, isStudent, timelst, seat_request, to_day, name,erweima):
if erweima == 1:
web = webdriver.Chrome(R"\chromedriver.exe") # 根据自身配置chromedriver位置
web.maximize_window()
web.get("https://kyfw.12306.cn/otn/resources/login.html") # 登录网站
web.execute_script(script)
while True: # 自旋等待用户扫描二维码成功并跳转登录界面
if web.current_url != initmyUrl:
time.sleep(1)
else:
print('登录成功!')
break
else: # 账号密码登录方式、将在下面展示
代码实现结果为:
TIPS:如还有疑问,欢迎留言
二、账号密码登录方式
超级鹰第三方库
超级鹰官网链接(点击跳转)
为什么要用到这个第三方库呢?原因就是12306那连人都难以分辨的验证码
接下来我将介绍怎么使用这个第三方库
其中代码为:
#!/usr/bin/env python
# coding:utf-8
import requests
from hashlib import md5
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()
if __name__ == '__main__':
chaojiying = Chaojiying_Client('超级鹰账号', '超级鹰密码', '申请的软件ID')
im = open('验证码图片', 'rb').read()
print(chaojiying.PostPic(im, 9004)) #9004为自定义端口号,通过12306验证码可使用9004端口
账号密码登录
通过使用超级鹰第三方库,我们实现了验证码的校验,如何实现接下来的滑块验证呢,请看接下来的代码:
else:
t = 5 # 由于第二次的验证码难度较大,我选择在验证失败后抛出异常,重新进入登录界面进行验证
while t:
t -= 1
try:
web = webdriver.Chrome(R"\chromedriver.exe") # 根据自身配置chromedriver位置
web.maximize_window()
web.get("https://kyfw.12306.cn/otn/resources/login.html") # 登录网站
web.execute_script(script) # 避免爬虫被发现
time.sleep(0.5)
web.find_element_by_xpath('/html/body/div[2]/div[2]/ul/li[2]/a').click() # 点击对应的账号密码登录按钮
time.sleep(0.5)
web.get_screenshot_as_file(r"new_image.png") # 截取整个页面
imgelement = web.find_element_by_xpath('//*[@id="J-loginImg"]') # 找到图片验证码的实际位置
rangle = (1252, 360, 1652, 595) # 需要根据自身电脑配置相对位置!!!!
i = Image.open("new_image.png")
frame4 = i.crop(rangle) # 从截图中再次截取我们需要的区域
frame4 = frame4.convert('RGB') # 渲染图片
frame4.save('check_image.jpg') # 保存为check_image图片
web.find_element_by_xpath('//*[@id="J-userName"]').send_keys(account) # 输入账号密码
web.find_element_by_xpath('//*[@id="J-password"]').send_keys(password)
im = open('check_image.jpg', 'rb').read() # 解析图片,返回地址
dic = chaojiying.PostPic(im, 9004)
result = dic['pic_str']
print(result)
rs_list = result.split("|")
time.sleep(0.5)
action = ActionChains(web) # 鼠标移位并点击
for rs in rs_list:
p_temp = rs.split(",")
x = int(p_temp[0])-58 # 需要根据自身电脑配置相对位置!!!!
y = int(p_temp[1])-33
print(x, y)
action.move_to_element_with_offset(imgelement, x, y).click().perform()
action = ActionChains(web)
web.find_element_by_xpath('//*[@id="J-login"]').click() # 点击按钮登录
time.sleep(3)
btn = web.find_element_by_xpath('//*[@id="nc_1_n1z"]') # 滑块验证码
ActionChains(web).drag_and_drop_by_offset(btn, 300, 0).perform()
time.sleep(3)
break
except Exception as e: # 验证码错误即重新登录
web.close()
print('验证码校验失败!正在重新登录')
改进方式:读者也可直接通过Xpath爬取当前界面的验证码图片,这样稍微简单点,博主懒癌犯了,请允许我划划水
结果展示:
代码汇总:
import time
import json
from PIL import Image
from selenium import webdriver
from chaojiying import Chaojiying_Client
from selenium.webdriver.common.keys import Keys
from selenium.webdriver.support.ui import Select
from selenium.webdriver.common.action_chains import ActionChains
chaojiying = Chaojiying_Client('超级鹰账号', '超级鹰密码', '软件ID')
initmyUrl = 'https://kyfw.12306.cn/otn/view/index.html'
script = 'Object.defineProperty(navigator,"webdriver",{get:() => false,});' # 修改navigator属性,避免爬虫被12306发现
def Login(account, password, from_station, to_station, isStudent, timelst, seat_request, to_day, name,erweima):
if erweima == 1:
web = webdriver.Chrome(R"\chromedriver.exe") # 根据自身配置chromedriver位置
web.maximize_window()
web.get("https://kyfw.12306.cn/otn/resources/login.html") # 登录网站
web.execute_script(script)
while True: # 自旋等待用户扫描二维码成功并跳转登录界面
if web.current_url != initmyUrl:
time.sleep(1)
else:
print('登录成功!')
break
else:
t = 5 # 由于第二次的验证码难度较大,我选择在验证失败后抛出异常,重新进入登录界面进行验证
while t:
t -= 1
try:
web = webdriver.Chrome(R"\chromedriver.exe") # 根据自身配置chromedriver位置
web.maximize_window()
web.get("https://kyfw.12306.cn/otn/resources/login.html") # 登录网站
web.execute_script(script) # 避免爬虫被发现
time.sleep(0.5)
web.find_element_by_xpath('/html/body/div[2]/div[2]/ul/li[2]/a').click() # 点击对应的账号密码登录按钮
time.sleep(0.5)
web.get_screenshot_as_file(r"new_image.png") # 截取整个页面
imgelement = web.find_element_by_xpath('//*[@id="J-loginImg"]') # 找到图片验证码的实际位置
rangle = (1252, 360, 1652, 595) # 需要根据自身电脑配置相对位置!!!!
i = Image.open("new_image.png")
frame4 = i.crop(rangle) # 从截图中再次截取我们需要的区域
frame4 = frame4.convert('RGB') # 渲染图片
frame4.save('check_image.jpg') # 保存为check_image图片
web.find_element_by_xpath('//*[@id="J-userName"]').send_keys(account) # 输入账号密码
web.find_element_by_xpath('//*[@id="J-password"]').send_keys(password)
im = open('check_image.jpg', 'rb').read() # 解析图片,返回地址
dic = chaojiying.PostPic(im, 9004)
result = dic['pic_str']
print(result)
rs_list = result.split("|")
time.sleep(0.5)
action = ActionChains(web) # 鼠标移位并点击
for rs in rs_list:
p_temp = rs.split(",")
x = int(p_temp[0])-58 # 需要根据自身电脑配置相对位置!!!!
y = int(p_temp[1])-33
print(x, y)
action.move_to_element_with_offset(imgelement, x, y).click().perform()
action = ActionChains(web)
web.find_element_by_xpath('//*[@id="J-login"]').click() # 点击按钮登录
time.sleep(3)
btn = web.find_element_by_xpath('//*[@id="nc_1_n1z"]') # 滑块验证码
ActionChains(web).drag_and_drop_by_offset(btn, 300, 0).perform()
time.sleep(3)
break
except Exception as e: # 验证码错误即重新登录
web.close()
print('验证码校验失败!正在重新登录')
博主将持续更新,欢迎关注!