Selenium之模拟登录铁路12306的示例代码

最近接触了一些selenium模块的相关知识,觉得还挺有意思的,于是决定亲自尝试写一些爬虫程序来强化selenium模块(一定要多尝试、多动手、多总结)。本文主要使用python爬虫来模拟登录铁路12306官网。这儿得吐槽一句,铁路12306网站的反爬机制做的还是比较好。

话不多说,下面跟小墨一起来学习如何通过爬虫来实现铁路12306的登录。

一、 验证码破解

当我们输入账号和密码后,在点击登录按钮之前,还需要对验证码进行操作。对验证码的识别,已经有相关的处理平台,我们只需要借助第三方平台即可。

1.注册并登录超级鹰账号:点击链接进行注册https://www.chaojiying.com/user/login/
2.点击购买题分,并进行充值;
3.点击软件id,创建一个软件Id(程序中会用到);
4.下载示例代码(开发文档—>选择相应的语言–>下载示例demo),python示例代码如下所示:

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()

二、Selenium功能简介

Selenium模块和爬虫之间的关联:
–便捷的获取网站中的动态加载数据
–便捷实现模拟登录

Selenium模块的使用流程:
–环境安装:pip install selenium
–下载浏览器的驱动程序(谷歌浏览器):
–下载路径:http://chromedriver.storage.googleapis.com/index.html
– 驱动程序和浏览器的映射关系:映射链接
–将下载好的驱动程序放在当前项目目录下

Selenium模块的相关方法:https://www.jb51.net/article/192259.htm

上述内容完成后,我们就可以正式进入正题了,是不是很期待,那就跟着小墨往下走吧。

三、模拟登录

1. 进入官网

#创建对象
#executable_path=path:下载好的驱动程序的路径
bro = webdriver.Chrome(executable_path='chromedriver.exe')
#12306的登录网址
bro.get('https://kyfw.12306.cn/otn/resources/login.html')
#窗口最大化
bro.maximize_window()

2、进入登录界面并获取验证码

#save_screenshot就是将当前页面进行截图且保存
bro.save_screenshot('aa.png')
#确定验证码图片对应的左上角和右下角的坐标(裁剪的区域就确定)
code_img_ele = bro.find_element_by_xpath('//*[@id="J-loginImg"]')
location = code_img_ele.location # 验证码图片左上角的坐标 x,y
#print('location:',location)
size = code_img_ele.size #验证码标签对应的长和宽
#print('size:',size)
#左上角和右下角坐标
rangle = (
int(location['x']), int(location['y']), int(location['x'] + size['width']), int(location['y'] + size['height']))
#至此验证码图片区域就确定下来了
i = Image.open('./aa.png')
code_img_name = './code.png'
#crop根据指定区域进行图片裁剪
frame = i.crop(rangle)
frame.save(code_img_name)
#将验证码图片提交给超级鹰进行识别
chaojiying = Chaojiying_Client('########', '#######', '#######')	#用户账号>>密码>>软件ID
im = open('code.png', 'rb').read()									#本地图片文件路径 来替换 a.jpg 有时WIN系统须要//
id=chaojiying.PostPic(im, 9004)['pic_id']       #截取的验证码照片以及验证码的类别代号
result = chaojiying.PostPic(im, 9004)['pic_str']     #识别结果
all_list = [] #要存储即将被点击的点的坐标 [[x1,y1],[x2,y2]]
#识别错误后,会返回题分,示例代码并没有这个,就是想让你花钱
chaojiying.ReportError(id)
if '|' in result:
 list_1 = result.split('|')
 print(list_1)
 count_1 = len(list_1)
 for i in range(count_1):
  xy_list = []
  x = int(list_1[i].split(',')[0])
  y = int(list_1[i].split(',')[1])
  xy_list.append(x)
  xy_list.append(y)
  all_list.append(xy_list)
else:
 x = int(result.split(',')[0])
 y = int(result.split(',')[1])
 xy_list = []
 xy_list.append(x)
 xy_list.append(y)
 all_list.append(xy_list)
#遍历列表,使用动作链对每一个列表元素对应的x,y指定的位置进行点击操作
for l in all_list:
 x = l[0]
 y = l[1]
 ActionChains(bro).move_to_element_with_offset(code_img_ele, x, y).click().perform()
 time.sleep(0.5)

这样我们就实现了验证码的识别操作。

3、输入账号和密码,并点击登录按钮

#输入账号和密码
 put1=bro.find_element_by_id('J-userName')
 #当验证码识别错误后,需要清空账号重新输入
 put1.clear()
 #输入账号
 put1.send_keys('########')
 time.sleep(1)
 put2=bro.find_element_by_id('J-password')
 put2.clear()
 #输入密码
 put2.send_keys('##########')
 time.sleep(1)
 #点击登录按钮
 bro.find_element_by_id('J-login').click()

点击登录按钮后,会出现如下图所示的弹框

因此,我们需要定位到该提示框,并实现滑块的向右滑动

4、滑块滑动

#处理提示框
time.sleep(0.5)
span=bro.find_element_by_xpath('//*[@id="nc_1_n1z"]')
action = ActionChains(bro)
#点击长按指定的标签
action.click_and_hold(span).perform()
action.drag_and_drop_by_offset(span,400,0).perform()

有的时候,当滑块移动后,会出现如下图所示的情况:

因此,我们需要点击刷新,并重新进行滑块的移动,所以对代码做稍微的改动:

while True:
  try:
   info=bro.find_element_by_xpath('//*[@id="J-slide-passcode"]/div/span').text
   print(info)
   if info=='哎呀,出错了,点击刷新再来一次':
   	 #点击刷新
    bro.find_element_by_xpath('//*[@id="J-slide-passcode"]/div/span/a').click()
    time.sleep(0.2)
    #重新移动滑块
    span = bro.find_element_by_xpath('//*[@id="nc_1_n1z"]')
    action = ActionChains(bro)
    # 点击长按指定的标签
    action.click_and_hold(span).perform()
    action.drag_and_drop_by_offset(span, 400, 0).perform()
    time.sleep(7)
  except:
   print('ok!')
   break

至此,我们便实现了铁路12306的登录,如下图所示

是不是觉得很简单啊。

5、完整代码

# -*- 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()

#使用selenium打开登录页面
from selenium import webdriver
import time
from PIL import Image
from selenium.webdriver import ActionChains
from selenium.webdriver.support import expected_conditions as EC, wait

#创建对象
#executable_path=path:下载好的驱动程序的路径
bro = webdriver.Chrome(executable_path='chromedriver.exe')
#12306的登录网址
bro.get('https://kyfw.12306.cn/otn/resources/login.html')
#窗口最大化
bro.maximize_window()
#点击账号登录
bro.find_element_by_xpath('/html/body/div[2]/div[2]/ul/li[2]/a').click()
time.sleep(1)
while True:
 try:
  #save_screenshot就是将当前页面进行截图且保存
  bro.save_screenshot('aa.png')
  #确定验证码图片对应的左上角和右下角的坐标(裁剪的区域就确定)
  code_img_ele = bro.find_element_by_xpath('//*[@id="J-loginImg"]')
  location = code_img_ele.location # 验证码图片左上角的坐标 x,y
  #print('location:',location)
  size = code_img_ele.size #验证码标签对应的长和宽
  #print('size:',size)
  #左上角和右下角坐标
  rangle = (
  int(location['x']), int(location['y']), int(location['x'] + size['width']), int(location['y'] + size['height']))
  #至此验证码图片区域就确定下来了
  i = Image.open('./aa.png')
  code_img_name = './code.png'
  #crop根据指定区域进行图片裁剪
  frame = i.crop(rangle)
  frame.save(code_img_name)
  #将验证码图片提交给超级鹰进行识别
  chaojiying = Chaojiying_Client('#####', '#######', '######')	#用户账号>>密码>>软件ID
  im = open('code.png', 'rb').read()									#本地图片文件路径 来替换 a.jpg 有时WIN系统须要//
  id=chaojiying.PostPic(im, 9004)['pic_id']       #截取的验证码照片以及验证码的类别代号
  result = chaojiying.PostPic(im, 9004)['pic_str']     #识别结果
  all_list = [] #要存储即将被点击的点的坐标 [[x1,y1],[x2,y2]]
  #识别错误后,会返回题分,官网给的demo并没有这一句,哈哈哈,坑吧,就是让你多花钱
  chaojiying.ReportError(id)
  if '|' in result:
   list_1 = result.split('|')
   print(list_1)
   count_1 = len(list_1)
   for i in range(count_1):
    xy_list = []
    x = int(list_1[i].split(',')[0])
    y = int(list_1[i].split(',')[1])
    xy_list.append(x)
    xy_list.append(y)
    all_list.append(xy_list)
  else:
   x = int(result.split(',')[0])
   y = int(result.split(',')[1])
   xy_list = []
   xy_list.append(x)
   xy_list.append(y)
   all_list.append(xy_list)
  #遍历列表,使用动作链对每一个列表元素对应的x,y指定的位置进行点击操作
  for l in all_list:
   x = l[0]
   y = l[1]
   ActionChains(bro).move_to_element_with_offset(code_img_ele, x, y).click().perform()
   time.sleep(0.5)
  #输入账号和密码
  put1=bro.find_element_by_id('J-userName')
  #当验证码识别错误后,需要清空账号重新输入
  put1.clear()
  put1.send_keys('username') #你的账号
  time.sleep(1)
  put2=bro.find_element_by_id('J-password')
  put2.clear()
  put2.send_keys('password') #你的密码
  time.sleep(1)
  bro.find_element_by_id('J-login').click()
  #处理提示框
  time.sleep(3)
  span=bro.find_element_by_xpath('//*[@id="nc_1_n1z"]')
  action = ActionChains(bro)
  #点击长按指定的标签
  action.click_and_hold(span).perform()
  action.drag_and_drop_by_offset(span,400,0).perform()
  time.sleep(8)
  while True:
   try:
    info=bro.find_element_by_xpath('//*[@id="J-slide-passcode"]/div/span').text
    print(info)
    if info=='哎呀,出错了,点击刷新再来一次':
     bro.find_element_by_xpath('//*[@id="J-slide-passcode"]/div/span/a').click()
     time.sleep(0.2)
     span = bro.find_element_by_xpath('//*[@id="nc_1_n1z"]')
     action = ActionChains(bro)
     # 点击长按指定的标签
     action.click_and_hold(span).perform()
     action.drag_and_drop_by_offset(span, 400, 0).perform()
     time.sleep(7)
   except:
    print('ok!')
    break
  #释放动作链
  action.release()
  break
 except:
  time.sleep(3)
time.sleep(12)
#登录成功
bro.find_element_by_link_text('确定').click()
time.sleep(0.5)
bro.find_element_by_link_text('首页').click()
#输入起点、终点以及时间,查询车票
start_city='北京'
end_city='上海'
date='2020-08-05'
#选择起点
bro.find_element_by_xpath('//*[@id="fromStationText"]').click()
time.sleep(2)
#这只遍历了热门城市,要是想遍历其他城市,自己写一个循环就行
city_list=bro.find_elements_by_xpath('//*[@id="ul_list1"]/li')
for city in city_list:
 if city.text==start_city:
  city.click()
  break
time.sleep(2)
#选择终点
bro.find_element_by_xpath('//*[@id="toStationText"]').click()
for city in city_list:
 if city.text==end_city:
  city.click()
  break
time.sleep(2)
js = "$('input[id=train_date]').removeAttr('readonly')"
bro.execute_script(js)
dt=bro.find_element_by_id('train_date')
dt.clear()
dt.send_keys(date)
time.sleep(2)
bro.find_element_by_xpath('/html/body/div[3]/div[2]/div/div[1]/div/div[1]/ul/li[1]/a').click()
time.sleep(0.5)
bro.find_element_by_xpath('//*[@id="isStudentDan"]/i').click()
time.sleep(2)
bro.find_element_by_id('search_one').click()
time.sleep(2)

到此这篇关于Selenium之模拟登录铁路12306的示例代码的文章就介绍到这了,更多相关Selenium 模拟登录12306内容请搜索我们以前的文章或继续浏览下面的相关文章希望大家以后多多支持我们!

(0)

相关推荐

  • Python+Selenium+phantomjs实现网页模拟登录和截图功能(windows环境)

    本文全部操作均在windows环境下 安装 Python Python是一种跨平台的计算机程序设计语言,它可以运行在Windows.Mac和各种Linux/Unix系统上.是一种面向对象的动态类型语言,最初被设计用于编写自动化脚本(shell),随着版本的不断更新和语言新功能的添加,越来越多被用于独立的.大型项目的开发 去Python的官网  www.python.org  下载安装 安装时勾选pip (python包管理工具),同时安装pip python安装好之后,打开命令行工具cmd,输入

  • selenium跳过webdriver检测并模拟登录淘宝

    简介 模拟登录淘宝已经不是一件新鲜的事情了,过去我曾经使用get/post方式进行爬虫,同时也加入IP代理池进行跳过检验,但随着大型网站的升级,采取该策略比较难实现了.因为你使用get/post方式进行爬取数据,会提示需要登录,而登录又是一大难题,需要滑动验证码验证.当你想使用IP代理池进行跳过检验时,发现登录时需要手机短信验证码验证,由此可以知道旧的全自动爬取数据对于大型网站比较困难了. selenium是一款优秀的WEB自动化测试工具,所以现在采用selenium进行半自动化爬取数据,支持模

  • 使用selenium模拟登录解决滑块验证问题的实现

    本次主要是使用selenium模拟登录网页端的TX新闻,本来最开始是模拟请求的,但是某一天突然发现,部分账号需要经过滑块验证才能正常登录,如果还是模拟请求,需要的参数太多了,找的心累.不过好在TX的滑块验证是他们自己开发的,没有极验那么复杂,当然相反的,想要模拟就得自己去一点点探索了,毕竟对极验滑块的破解,网上已经可以找到现成的代码来用了.下面说一下模拟的实现过程和我遇见的问题. 1.登录入口 我是通过点击打开链接来当做登录入口的 部分代码实现: driver = webdriver.Chrom

  • Selenium之模拟登录铁路12306的示例代码

    最近接触了一些selenium模块的相关知识,觉得还挺有意思的,于是决定亲自尝试写一些爬虫程序来强化selenium模块(一定要多尝试.多动手.多总结).本文主要使用python爬虫来模拟登录铁路12306官网.这儿得吐槽一句,铁路12306网站的反爬机制做的还是比较好. 话不多说,下面跟小墨一起来学习如何通过爬虫来实现铁路12306的登录. 一. 验证码破解 当我们输入账号和密码后,在点击登录按钮之前,还需要对验证码进行操作.对验证码的识别,已经有相关的处理平台,我们只需要借助第三方平台即可.

  • python 模拟登录B站的示例代码

    需要将模拟的浏览器,添加到环境变量中哦.代码中用的是chrome from selenium import webdriver from selenium.webdriver.support.ui import WebDriverWait from selenium.webdriver.support import expected_conditions as EC from selenium.webdriver.common.by import By from selenium.webdriv

  • C语言模拟实现密码输入的示例代码

    目录 引言 思路分析 代码实现 代码分析 引言 登录账号时我们要输入密码,密码输入错误时会提示密码错误.有时密码的输入次数会被限制,例如银行卡,当我们3次密码都输入错误时卡会被冻结.下面用C语言模拟实现密码输入. 思路分析 首先要确立一个正确密码,再确定密码输入限制次数,接着用一个scanf语句读取用户输入的密码.将用户输入的密码和先前确定的密码进行比较,如果密码输入正确就显示密码正确,如果密码输入错误就提示密码错误,并告诉用户还有几次输入机会. 代码实现 #include<stdio.h>

  • koa2实现登录注册功能的示例代码

    本文介绍了koa2实现登录注册功能的示例代码,分享给大家,具体如下: 这个主要结合前几天的内容,做个实际案例的效果 版本: 项目结构: 前几天,我们把注册和登录的页面demo实现了,今天我们主要实现这么几个内容 注册新用户 判断该邮箱是否注册过 登录判断是否注册过 登录时的密码的正确 本文代码地址:https://github.com/xiaqijian/koa2-lessons/tree/master/lesson6 明天,我们将利用session实现登录状态判断 今天的这篇是在之前的代码基础

  • Spring Security OAuth2 实现登录互踢的示例代码

    本文主要介绍了Spring Security OAuth2 实现登录互踢的示例代码,分享给大家,具体如下: 背景说明 一个账号只能一处登录,类似的业务需求在现有后管类系统是非常常见的. 但在原有的 spring security oauth2 令牌方法流程(所谓的登录)无法满足类似的需求. 我们先来看 TokenEndpoint 的方法流程 客户端 带参访问 /oauth/token 接口,最后去调用 TokenGranter TokenGranter 根据不同的授权类型,获取用户认证信息 并去

  • React实现登录表单的示例代码

    作为一个Vue用户,是时候扩展一下React了,从引入antd.配置less.router,终于实现了一个简单的登录表单. 代码如下: import React from 'react'; import { Input, Button, message } from "antd"; import { UserOutlined, LockOutlined, EyeInvisibleOutlined, EyeTwoTone } from '@ant-design/icons'; impor

  • vue实现登录注册模板的示例代码

    模板1: login.vue <template> <p class="login"> <el-tabs v-model="activeName" @tab-click="handleClick"> <el-tab-pane label="登录" name="first"> <el-form :model="ruleForm" :ru

  • Python selenium+cookie实现免密登陆的示例代码

    目录 获取cookies: 携带cookies实现免密登陆: 今天爬取airbnb的租房数据时,遇到了登陆问题.自己动手解决了一下. 我们知道,http是无状态的,那么网页如何实现用户登陆注册功能呢?Session和Cookie就是为了满足这种需求出现的技术. 首先介绍一下Session和Cookie的概念. 在Web中Session对象存储特定用户会话所需的属性及配置信息.这样,当用户在应用程序的Web页之间跳转时,存储在Session对象中的变量将不会丢失,而是在整个用户会话中一直存在下去.

  • 基于PHP实现JWT登录鉴权的示例代码

    目录 一.什么是JWT 1.简介 2.JWT的组成 3.JWT验证流程和特点 二.相关问题 三.PHP实现 1.引入依赖 2.功能实现 3.封装工具类如下 一.什么是JWT 1.简介 JWT(JSON Web Token)是为了在网络应用环境间传递声明而执行的一种基于JSON的开放标准. 简单的说,JWT就是一种Token的编码算法,服务器端负责根据一个密码和算法生成Token,然后发给客户端,客户端只负责后面每次请求都在HTTP header里面带上这个Token,服务器负责验证这个Token

  • 基于Java实现QQ登录注册功能的示例代码

    目录 前言 实现代码 登录页面 注册页面 效果展示 前言 本文主要应用的技术有:GUI.JDBC.多线程 实现的功能具体如下: 1.登录功能 2.注册功能 3.是否隐藏密码的选择以及实现功能 4.选择性别功能 5.密码与确认密码功能 6.登录页面实时展示当前的时间 7.当登录时用户名与密码在数据库中没有相匹配的数据,则会跳转到注册页面上去. 8.同样,注册完毕后,数据会运用JDBC将数据写入数据库中,然后跳转回登录页面. 实现代码 登录页面 import javax.swing.*; impor

随机推荐