去哪儿网输入框三种输入方式(selenium webdriver 干货)
在机票预定的页面,输入出发城市和到达城市输入框的时候, 发现直接使用sendkeys不好使,
大部分情况出现输入某城市后没有输入进去, 经过几天的研究,发现可以采取三种方式:
1. 先点击输入框,待弹出 城市选择框之后,点击相应的城市
2. 缓慢输入城市的缩略字母或者城市的名字的部分,会显示出待选城市的下拉列表,进而从下拉列表中选择相应的城市.
3. 直接执行 js脚本对input的value设置为想要的值
首先说一下第三种方式:
JavascriptExecutor js = (JavascriptExecutor) driver;
js.executeScript("arguments[0].value=\"北京\"", from_inpox);
执行效果最好,
22:35:34.885 INFO - Executing: [execute script: arguments[0].value="北京", [[[Ch
romeDriver: chrome on XP (6452a4a961be7bffa2af9d1b63f3d111)] -> xpath: //div[@id
='js_flighttype_tab_domestic']//input[@name='fromCity']]]])

如上图所演示,两种方式均是用户真实行为。
采取第一种方式:
- 首先定位到输入框
- 点击输入框
- 从弹出的热门城市框中点击所需要的城市
WebElement from_inpox = driver
.findElement(By.xpath("//div[@id='js_flighttype_tab_domestic']//input[@name='fromCity']"));
Actions actions = new Actions(driver);
actions.moveToElement(from_inpox).click().perform();
driver.findElement(By
.xpath("//div[@data-panel='domesticfrom-flight-hotcity-from']//a[@class='js-hotcitylist' and text()='西安']"))
.click();
这里我并没有直接使用click, 而是使用Actions,原因是我在对到达城市操作时,发现经常报element can't be clicked这样的错误,
大意是,当要点击到达城市输入框,其实是被上层的元素遮挡,没法使用click方法,但是可以使用Actions的moveToElement方法之后可以click
或者采取滚动到该元素,调用JS
JavascriptExecutor jse = (JavascriptExecutor) driver;
jse.executeScript("arguments[0].scrollIntoView()",element);
之后就可进行click操作.
如果使用第二种方法,就会遇到一个很大的问题:
如何定位到JS生成的下拉列表的城市?Firebug定位之前列表就消失!
看上去很难哈,反复尝试无所成, 最后突然想起既然是JS生成的,何不使用浏览器的JS debug功能,设置断点一步一步
果不其然,药到病除。nice job~

思路有了,跟我一起做,点开firebug ,切换到“脚本”界面,首先在输入框输入单字母s,待弹出下拉列表后,单击左侧的插入断点操作
你会发现该下拉框被冻结,不错呦,之后切换到html界面进行定位。
不光是去哪网,像百度输入框也可以采取这样的办法,JS设置断点,js的弹出框,弹出菜单就会冻结.
接下来我的输入就是选择下拉菜单中所需城市:
from_inpox.clear();
from_inpox.sendKeys("BJ");
Thread.sleep(8000);
By bj=new By.ByXPath("//div[@class='qcbox-fixed js-suggestcontainer']//td[contains(text(),'北京')]");
if(isElementPresent(driver,bj,20))
{
driver.findElement(bj).click();
}
所要注意的是,下拉菜单中未必弹出那么快,需要做一次等待,在选择下拉菜单的时候需要做一次判断,当然这个判断方法是使用WebDriverWait
/**
* @author Young
* @param driver
* @param by
* @param timeOut
* @return
*/
public static boolean isElementPresent(WebDriver driver, final By by, int timeOut) {
WebDriverWait wait = new WebDriverWait(driver, timeOut);
boolean isPresent = false;
isPresent = wait.until(new ExpectedCondition<WebElement>() {
@Override
public WebElement apply(WebDriver d) {
return d.findElement(by);
}
}).isDisplayed();
return isPresent; }
依然不够完美,为什么这么说,如果元素没有出现,并不是返回的false而是直接抛异常,并不是期望的,所以修改为findElements
如果找不到,返回List长度必然为0,进而返回false而不是抛出异常
/**
* @author Young
* @param driver
* @param by
* @param timeOut
* @return
* @throws InterruptedException
*/
public static boolean isElementPresent(WebDriver driver, final By by,
int timeOut) throws InterruptedException {
boolean isPresent = false;
Thread.sleep(timeOut * 1000);
List<WebElement> we = driver.findElements(by);
if (we.size() != 0) {
isPresent = true;
}
return isPresent;
}
测试步骤:
1.选择出发城市-> 北京
到达城市->上海
选择今天之后的七天
点击search button
2.选择某带“每段航班均需缴纳税费” 的订单
public static void main(String[] args) throws InterruptedException {
WebDriver driver = DriverFactory.getChromeDriver();
driver.get("http://flight.qunar.com/");
driver.manage().window().maximize();
driver.manage().timeouts().implicitlyWait(30, TimeUnit.SECONDS);
driver.manage().timeouts().pageLoadTimeout(30, TimeUnit.SECONDS);
WebElement from_inpox = driver
.findElement(By
.xpath("//div[@id='js_flighttype_tab_domestic']//input[@name='fromCity']"));
WebElement to_inpox = driver
.findElement(By
.xpath("//div[@id='js_flighttype_tab_domestic']//input[@name='toCity']"));
WebElement from_date = driver
.findElement(By
.xpath("//div[@id='js_flighttype_tab_domestic']//input[@name='fromDate']"));
WebElement sigleWayCheckBox = driver
.findElement(By
.xpath("//div[@id='js_flighttype_tab_domestic']//input[@class='inp_chk js-searchtype-oneway']"));
if (!sigleWayCheckBox.isSelected()) {
sigleWayCheckBox.click();
}
from_inpox.clear();
from_inpox.sendKeys("BJ");
Thread.sleep(8000);
By bj = new By.ByXPath(
"//div[@class='qcbox-fixed js-suggestcontainer']//td[contains(text(),'北京')]");
if (isElementPresent(driver, bj, 20)) {
driver.findElement(bj).click();
}
to_inpox.clear();
to_inpox.sendKeys("SH");
Thread.sleep(8000);
By sh = new By.ByXPath(
"//div[@class='qcbox-fixed js-suggestcontainer']//td[contains(text(),'上海')]");
if (isElementPresent(driver, sh, 20)) {
driver.findElement(sh).click();
}
// Actions actions = new Actions(driver);
// actions.moveToElement(from_inpox).click().perform();
// driver.findElement(
// By.xpath("//div[@data-panel='domesticfrom-flight-hotcity-from']//a[@class='js-hotcitylist' and text()='西安']"))
// .click();
// driver.manage().timeouts().implicitlyWait(30, TimeUnit.SECONDS);
// driver.manage().timeouts().pageLoadTimeout(30, TimeUnit.SECONDS);
// actions.moveToElement(to_inpox).click().perform();
// driver.findElement(
// By.xpath("//div[@data-panel='domesticto-flight-hotcity-to']//a[@class='js-hotcitylist' and text()='北京']"))
// .click();
// driver.manage().timeouts().implicitlyWait(30, TimeUnit.SECONDS);
// driver.manage().timeouts().pageLoadTimeout(30, TimeUnit.SECONDS);
from_date.clear();
from_date.sendKeys(getDateAfterToday(7));
WebElement search = driver
.findElement(By
.xpath("//div[@id='js_flighttype_tab_domestic']//button[@class='btn_search']"));
search.submit();
driver.manage().timeouts().implicitlyWait(30, TimeUnit.SECONDS);
driver.manage().timeouts().pageLoadTimeout(30, TimeUnit.SECONDS);
WebElement page2 = driver.findElement(By
.xpath("//div[@id='hdivPager']/a[@value='2']"));
JavascriptExecutor jse = (JavascriptExecutor) driver;
jse.executeScript("arguments[0].scrollIntoView()", page2);
page2.click();
driver.manage().timeouts().implicitlyWait(30, TimeUnit.SECONDS);
driver.manage().timeouts().pageLoadTimeout(30, TimeUnit.SECONDS);
driver.findElement(
By.xpath("(//div[@class='avt_trans']//p[contains(text(),'每段航班均需缴纳税费')]/ancestor::div//div[@class='a_booking']/a)[3]"))
.click();
driver.findElement(
By.xpath("//div[@id='flightbarXI883']//div[@class='t_bk']/a"))
.click();
}
public static String getDateAfterToday(int dateAfterToday) {
Calendar cal = Calendar.getInstance();
cal.add(Calendar.DATE, +dateAfterToday);
System.out.println(cal.getTime().toString());
Date date = cal.getTime();
SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd");
System.out.println(df.format(date));
return df.format(date);
}
/**
* @author Young
* @param driver
* @param by
* @param timeOut
* @return
* @throws InterruptedException
*/
public static boolean isElementPresent(WebDriver driver, final By by,
int timeOut) throws InterruptedException {
boolean isPresent = false;
Thread.sleep(timeOut * 1000);
List<WebElement> we = driver.findElements(by);
if (we.size() != 0) {
isPresent = true;
}
return isPresent;
}
效果如下:

去哪儿网输入框三种输入方式(selenium webdriver 干货)的更多相关文章
- 输入框三种输入方式(selenium webdriver 干货)
在机票预定的页面,输入出发城市和到达城市输入框的时候, 发现直接使用sendkeys不好使, 大部分情况出现输入某城市后没有输入进去, 经过几天的研究,发现可以采取三种方式: 1. 先点击输入框,待弹 ...
- python中的三种输入方式
python中的三种输入方式 python2.X python2.x中以下三个函数都支持: raw_input() input() sys.stdin.readline() raw_input( )将 ...
- 【转】vue.js三种安装方式
Vue.js(读音 /vjuː/, 类似于 view)是一个构建数据驱动的 web 界面的渐进式框架.Vue.js 的目标是通过尽可能简单的 API 实现响应的数据绑定和组合的视图组件.它不仅易于上手 ...
- vue.js三种安装方式
Vue.js(读音 /vjuː/, 类似于 view)是一个构建数据驱动的 web 界面的渐进式框架.Vue.js 的目标是通过尽可能简单的 API 实现响应的数据绑定和组合的视图组件.它不仅易于上手 ...
- 多对多三种创建方式、forms组件、cookies与session
多对多三种创建方式.forms组件.cookies与session 一.多对多三种创建方式 1.全自动 # 优势:不需要你手动创建第三张表 # 不足:由于第三张表不是你手动创建的,也就意味着第三张表字 ...
- 多对多的三种创建方式-forms相关组件-钩子函数-cookie与session
多对多的三种创建方式 1.全自动(推荐使用的**) 优势:第三张可以任意的扩展字段 缺点:ORM查询不方便,如果后续字段增加更改时不便添加修改 manyToManyField创建的第三张表属于虚拟的, ...
- MyEclipse中web服务器的三种配置方式
初学Javaweb开发的人们都会遇到一个问题,就是服务器环境的搭建配置问题.下面介绍三种服务器的搭建方式. 直接修改server.xml文件 当你写了一个web应用程序(jsp/servlet),想通 ...
- SignalR代理对象异常:Uncaught TypeError: Cannot read property 'client' of undefined 推出的结论 SignalR 简单示例 通过三个DEMO学会SignalR的三种实现方式 SignalR推送框架两个项目永久连接通讯使用 SignalR 集线器简单实例2 用SignalR创建实时永久长连接异步网络应用程序
SignalR代理对象异常:Uncaught TypeError: Cannot read property 'client' of undefined 推出的结论 异常汇总:http://www ...
- grub安装的 三种安装方式
1. 引言 grub是什么?最常态的理解,grub是一个bootloader或者是一个bootmanager,通过grub可以引导种类丰富的系统,如linux.freebsd.windows等.但一旦 ...
随机推荐
- 深入理解Java:内部类
什么是内部类? 内部类是指在一个外部类的内部再定义一个类.内部类作为外部类的一个成员,并且依附于外部类而存在的.内部类可为静态,可用protected和private修饰(而外部类只能使用public ...
- MarkdownPad2 Pro v2.4.2.29969 专业中文破解版完美支持table表格语法
在网上搞了半天,终于搞定了支持table简写语法的markdown软件. 下载地址:http://download.csdn.net/detail/wang_jun_hua/8180717 下载包内含 ...
- URLDecoder解析url编码
try { strJson = URLDecoder.decode(strJson, "utf-8"); } catch (UnsupportedEncodingException ...
- jquery-抖动图组轮播动画
JQ匀速抖动图组轮播动画 一.HTML+CSS <!DOCTYPE html> <html lang="en" xmlns="http://www.w3 ...
- Coding 及 git 的工程使用方法
在过去的两周,同学们除了在学习 C 语言之外,还在学习如何利用 git 将自己的代码上传到 coding 中.也有大量的同学,成功的上传了代码.但是,实际上大部分同学的用法都不合理.这里,以一 ...
- LCS问题
最长公共子序列问题 1.这里pre数组表示回溯的方式,状态转移方程!!! #include <iostream> #include <algorithm> #include & ...
- 【工具使用】sublime text3
import urllib.request,os,hashlib; h = 'df21e130d211cfc94d9b0905775a7c0f' + '1e3d39e33b79698005270310 ...
- linux免交互登陆远程主机并执行命令(密钥对和Expect)
原文章摘自:http://lizhenliang.blog.51cto.com/7876557/1607723/ Linux下实现免交互登陆一般有两种: 1. SSH无密码认证方式 客户端使用ssh- ...
- 【原创】cs+html+js+css模式(六):改造ajax.js,从原来的原生态js修改为依赖于jquery插件
由于原有的ajax可能在性能上,对于jquery的支持不够并且不够方便,开发人员使用的时候需要知道我们内部指定的后缀文件的设置,基于这个前提我们进行了js的改造 // 使用闭包开发插件 ( ...
- centos 防火墙
让防火墙放通tcp的 80端口: [root@localhost ~]# firewall-cmd --zone=public --add-port=80/tcp --permanent 重启防火墙以 ...