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内容请搜索我们以前的文章或继续浏览下面的相关文章希望大家以后多多支持我们!

时间: 2020-07-31

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

Python模拟登录之滑块验证码的破解(实例代码)

模拟登录之滑块验证码的破解,具体代码如下所示: # 图像处理标准库 from PIL import Image # web测试 from selenium import webdriver # 鼠标操作 from selenium.webdriver.common.action_chains import ActionChains # 等待时间 产生随机数 import time, random # 滑块移动轨迹 def get_tracks1(distance): # 初速度 v = 0 #

python selenium UI自动化解决验证码的4种方法

本文介绍了python selenium UI自动化解决验证码的4种方法,分享给大家,具体如下: 测试环境 windows7+ firefox50+ geckodriver # firefox浏览器驱动 python3 selenium3 selenium UI自动化解决验证码的4种方法:去掉验证码.设置万能码.验证码识别技术-tesseract.添加cookie登录,本次主要讲解验证码识别技术-tesseract和添加cookie登录. 1. 去掉验证码 去掉验证码,直接通过用户名和密码登陆网

python编程使用selenium模拟登陆淘宝实例代码

selenium简介 selenium 是一个web的自动化测试工具,不少学习功能自动化的同学开始首选selenium ,相因为它相比QTP有诸多有点: * 免费,也不用再为破解QTP而大伤脑筋 * 小巧,对于不同的语言它只是一个包而已,而QTP需要下载安装1个多G 的程序. * 这也是最重要的一点,不管你以前更熟悉C. java.ruby.python.或都是C# ,你都可以通过selenium完成自动化测试,而QTP只支持VBS * 支持多平台:windows.linux.MAC ,支持多浏

Python中Selenium模拟JQuery滑动解锁实例

本文介绍了Python中Selenium模拟JQuery滑动解锁实例,分享给大家,也给自己留个笔记 滑动解锁一直做UI自动化的难点之一,我补一篇滑动解锁的例子,希望能给初做Web UI自动化测试的同学一些思路. 首先先看个例子. 当我手动点击滑块时,改变的只是样式: 1.slide-to-unlock-handle 表示滑块,滑块的左边距在变大(因为它在向右移动嘛!) 2.Slide-tounlock-progress 表示滑过之后的背景黄色,黄色的宽度在增加,因为滑动经过的地方都变黄了. 除些

PHP Curl模拟登录微信公众平台、新浪微博实例代码

使用curl之前先打开curl配置,具体方式百度一下就知道,开启curl扩展.密码用md5加密,这是经过测试成功的,把用户跟密码改成你的就行了. 下面一段代码给大家介绍php使用curl模拟登录微信公众平台,具体代码如下所示: <?php //模拟微信登入 $cookie_file = tempnam('./temp','cookie'); $login_url = 'https://mp.weixin.qq.com/cgi-bin/login'; $pwd = md5("********

C#使用ImitateLogin模拟登录百度

在之前的文章中,我已经介绍过一个社交网站模拟登录的类库:imitate-login ,这是一个通过c#的HttpWebRequest来模拟网站登录的库,之前实现了微博网页版和微博Wap版:现在,模拟百度登录的部分也已经完成.由于个人时间的限制,加上目前有多个项目在同时进行,因此更新频率会根据项目关注度来决定(Star & fork). 这个类库的使用方法非常简单,仅对外提供一个方法: LoginResult Login(1: string userName, 2: string password

PHP使用Curl实现模拟登录及抓取数据功能示例

本文实例讲述了PHP使用Curl实现模拟登录及抓取数据功能.分享给大家供大家参考,具体如下: 使用PHP的Curl扩展库可以模拟实现登录,并抓取一些需要用户账号登录以后才能查看的数据.具体实现的流程如下(个人总结): 1. 首先需要对相应的登录页面的html源代码进行分析,获得一些必要的信息: (1)登录页面的地址: (2)验证码的地址: (3)登录表单需要提交的各个字段的名称和提交方式: (4)登录表单提交的地址: (5)另外要需要知道要抓取的数据所在的地址. 2. 获取cookie并存储(针