主要的核心思想是取cookie然后发查询请求,不需要浏览器做代理(转)

需求是催生项目和推进项目的不竭动力。

背景:

  最近,因为媳妇要做个B超检查,想着去大医院查查应该更放心,所以就把目标瞄准在A医院。早已耳闻A院一号难求万人空巷,所以把所有能接触到的机会都看了一遍,线下听传闻说早上徐亚5点左右去排队还未必能排上,线上主要有以下两个来源:

1.支付宝

  在支付宝的城市服务中,定位到指定城市,是能够看一些医院提供了预约挂号接口的,显然A医院当之无愧也在其中。

  简便易用的支付宝用户体验,即便是第一次来也好像是经常使用这项服务般熟练。找到A院,搜索妇产科,在list中有若干医生,有的标注无号源,有的标注可预约,大抵如下:

  于是满怀激动的点击"可预约",可是弹出来的却不是我想要的结果--!

  后来听到诸如凌晨12点会有号放出,但是最终也是收到同样冷冰冰的弹出窗口。对于用此招挂上号的我深表佩服,只是抛开这个不说,感觉A院在支付宝这块的投入太低,UI设计也很呆板,最主要的是抢不到号。

2.百度医生

  相对来说,百度医生要比上面做的实诚的多,有就是有,没有就是没有。不管是PC端还是app端,用户界面更加柔和smooth。

  于是我把希望寄托在这里,但是A院的号难抢,这是事实。而百度医生我觉得还有一块空白可以实现的就是监控机制,好比12306可以刷票一样,添加这个模块,相信app的下载量和使用量会提高一个"当量"。

很显然,这个功能,还没有,那我只能自己动手了~~~

我的思路

  1. 百度从医院拿数据,那我就从百度拿数据。我能够监控百度医生放出来的消息,就基本与医院同步了;

  2. 我要使用的是百度医生,但是这个需要登录,而且登录方式只有使用手机号+验证码的方式。这个方法可行,但是需要中间sleep以输入验证码,或者是调用短信接口,显然这两个都不是一个很好的途径,时间金钱成本高,用户体验差;

  3. 于是我想到,可以先登录百度账户(用户名+密码),然后利用这个账户进入百度医生,就免去了短信验证这个环节。

码前预热

1. 框架选择

毫无疑问,我们采用selenium,一款web测试应用工具,模拟我在浏览器上的操作。可以基于IE、FF、Chrome等等浏览器,实现启动关闭浏览器/页面,在页面上点击、定位元素等相应操作。关于selenium webdriver的背景知识就不做介绍,一篇博文显然难以阐述清楚。

2. 工具使用

在使用selenium过程中,页面元素的定位是个核心问题。我们可以使用By类下面的By.name,By.id,By.linkText分别获取获取name属性,id属性,超链接文本。这些方式的定位我们直接可以在DOM结构中看出来,其中比较复杂的是xpath,需要根据DOM结构实现定位,这时候我们需要一个工具可以实时的测试我们的xpath表达式是否能够正确定位到指定元素。

a.在Firefox浏览器中,我们可以安装插件FirePath

  这里我们通过字符串".//*[@id=‘su‘]"就能够定位到"百度一下"这个按钮

b.在chrome里面,我们可以下载插件XPath Helper,有关它的用户,请参看

http://www.chromein.com/crx_11654.html

思路有了,工具齐了,那就开始着手做吧

1.启动chrome浏览器

  需要下载chrome的驱动

?


1

2

System.setProperty ( "webdriver.chrome.driver" , "C:\\Users\\Administrator\\Downloads\\chromedriver_win32\\chromedriver.exe" );

WebDriver driver = new ChromeDriver();

 

2.定位元素执行动作

  如定位百度页面的登录按钮,并执行点击操作

?


1

2

WebElement loginLink = driver.findElement(By.xpath(".//*[@id=‘u1‘]/a[7]"));

loginLink.click();

  

3.等待页面加载完成

  有时候在driver.get()到某个页面时,如果页面没有加载完成,这时候去定位元素容易抛出异常,所以需要加入等待页面加载完成的功能。这里将其封装在一个函数中:

?


1

2

3

4

5

6

7

8

9

10

public static void waitForLoad(WebDriver driver) {

ExpectedCondition<Boolean> pageLoad= new

ExpectedCondition<Boolean>() {

public Boolean apply(WebDriver driver) {

return ((JavascriptExecutor)driver).executeScript("return document.readyState").equals("complete");

}

};

WebDriverWait wait = new WebDriverWait(driver, 30);

wait.until(pageLoad);

}

  

4.遇到异常重新启动机制

  监控的原理在于间歇性的点击相应的科室并监听页面中是否有想要的元素出现(如出现预约挂号),如果出现则点击进入相应界面,如果没有出现则一直监听。

  但是在实测过程中,发现持续点击某科室会出现页面一直加载的情况,这时候会抛出异常,程序无法正常进行。

  所以在这里捕获异常,通过递归调用的思想,关闭先前的driver对象,并调用自己重新生成一份监听driver对象,从而保证程序正常执行,提高了程序的健壮性。

?


1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

try {

WebDriverWait wait = new WebDriverWait(driver,7000);

wait.until(new ExpectedCondition<WebElement>(){

public WebElement apply(WebDriver d) {

try {

Thread.sleep(2000);//为避免给baidu早成麻烦,每2秒监听一次

} catch (InterruptedException e) {

e.printStackTrace();

}

departLink.click();//departLink为妇产科的文本链接

monitoringTimes++;//监听的次数

System.out.println("第" + monitoringTimes + "次监控");

return d.findElement(By.xpath("//*[@id=‘doctor-info-list‘]/descendant::*[contains(text(), ‘预约挂号‘)][1]"));

}

});

waitForLoad(driver);

} catch (Exception e) {

ticket = true;

System.out.println("抱歉,目前余号不足,请稍后再试");

}finally{

if(ticket){

driver.close();

startMonitor();//递归调用

}

}

  

5.成果展示

  但从程序来说,可以现实自动抢号功能,已成功预约到非妇产科以外科室的号。

  运行到监控的页面并监听:

  实时监听过程:

难点和展望

  • dom结构变动,会导致无法正常定位;
  • 代码执行过程,有时会抛出异常,需要处理;
  • 频繁的登录,需要在登录界面输入验证码,验证码的识别可以采用OCR破解;
  • 最好做成一个客户端,提供给用户自定义输入医院和科室乃至指定时间段或医生

一般情况下是登录成功后取到cookie直接放Python里跑一下就完事,几乎不用考虑掉线的情况。

http://www.cnblogs.com/bigdataZJ/p/hittest.html

时间: 2024-10-16 06:32:13

主要的核心思想是取cookie然后发查询请求,不需要浏览器做代理(转)的相关文章

jQuery的核心思想

jQuery?----www.jQuery.com jQuery的理念:write less, do more jQuery的成就:世界排名前100的公司,46%都在使用jQuery,远远超过其他库,微软公司甚至把jQuery库 作为了他们的官方库. what is jQuery?(这是我复制官网上的介绍,觉得说的很专业) jQuery is a fast, small, and feature-rich(功能丰富) JavaScript library. It makes things lik

java核心思想

第一章 多线程 多线程和多进程之间的区别: 本质区别在于每个进程有他自己的变量的完备集,线程则共享相同的数据,这个听起来似乎有些危险,事实上也的确如此,你将会在本章后面的内容中看到这个问题,尽管如此,对于程序来说,共享的变量使线程之间的通信 比进程间的通信更加有效简单,而且,对于某些操作系统而言,线程比进程更加轻量级.创建和销毁单个线程比发起进程的开销要小很多. 线程优先级 在Java程序设计语言中,每一个线程都有一个优先级,默认情况下,一个线程继承他的父线程的优先级,一个线程的父线程就是启动他

《深入理解SPARK:核心思想与源码分析》——SparkContext的初始化(中)

<深入理解Spark:核心思想与源码分析>一书前言的内容请看链接<深入理解SPARK:核心思想与源码分析>一书正式出版上市 <深入理解Spark:核心思想与源码分析>一书第一章的内容请看链接<第1章 环境准备> <深入理解Spark:核心思想与源码分析>一书第二章的内容请看链接<第2章 SPARK设计理念与基本架构> 由于本书的第3章内容较多,所以打算分别开辟三篇随笔分别展现. <深入理解Spark:核心思想与源码分析>一

详解Spring框架的核心思想之IOC

微信号:GitShare微信公众号:爱折腾的稻草如有问题或建议,请在公众号留言[1] 前续 为帮助广大SpringBoot用户达到"知其然,更需知其所以然"的境界,作者将通过SpringBoot系列文章全方位对SpringBoot2.0.0.RELEASE版本深入分解剖析,让您深刻的理解其内部工作原理. No.1 Spring是什么 为了让更多的朋友了解Spring,首先科普一下Spring!有兴趣的朋友可以去Spring官网逛逛,地址是:https://spring.io/ The

vue.js学习笔记(一):什么是mvvm框架,vue.js的核心思想

一:MVVM框架 MVVM框架的应用场景:  1.针对具有复杂交互逻辑的前端应用 2.提供基础的架构抽象 3.提供ajax数据持久化,保证前端用户体验 二:vue.js的核心思想 (一):数据驱动 (二):数据响应原理 (三):组件化 (四)组件设计原则 1:页面上每个独立的可视/可交互区域视为一个组件 2:每个组件对应一个工程目录,组件所需要的各种资源在这个目录下就近维护 3:页面只不过是组件的容器,组件可以嵌套自由组合形成完整的页面

Rookey.Frame v1.0 视频教程之三发布-框架核心思想介绍

本期发布视频: (三)Rookey.Frame v1.0框架核心思想 介绍了Rookey.Frame v1.0框架搭建的核心思想,将框架核心思想理解清楚,对框架运行就会得心应手 官方视频教程: http://rookey.gotoip2.com/Page/Example.html?page=Example&flag=Video 下期视频将介绍如何通过Rookey.Frame v1.0极速开发平台项目结构及核心代码介绍

【JavaScript】JS跨域设置和取Cookie

cookie 是存储于访问者的计算机中的变量.每当同一台计算机通过浏览器请求某个页面时,就会发送这个 cookie.你可以使用 JavaScript 来创建和取回 cookie 的值.本文主要JS怎样读取Cookie以及域的设置. AD: 在Javascript脚本里,一个cookie 实际就是一个字符串属性.当你读取cookie的值时,就得到一个字符串,里面当前WEB页使用的所有cookies的名称和值.每个cookie除了 name名称和value值这两个属性以外,还有四个属性.这些属性是:

hadoop的核心思想【转】

[转自]:http://www.superwu.cn/2014/01/10/963/ 1.1.1. hadoop的核心思想 Hadoop包括两大核心,分布式存储系统和分布式计算系统. 1.1.1.1. 分布式存储 为什么数据需要存储在分布式的系统中哪,难道单一的计算机存储不了吗,难道现在的几个TB的硬盘装不下这些数据吗?事实上,确实装不下.比如,很多的电信通话记录就存储在很多台服务器的很多硬盘中.那么,要处理这么多数据,必须从一台一台服务器分别读取数据和写入数据,太麻烦了! 我们希望有一种文件系

RAID2.0核心思想:数据保护与物理资源管理域分离

记得在2013年末的时候,开始将存储虚拟化为主导的数据保护技术归纳为RAID2.0.从市场的角度来看,这个一个非常好的概念,一方面可以延续传统RAID的思想,大家可以很容易明白这是一种数据保护技术:另一方面又表述了这是一种传统RAID的技术延伸,而且具有更新换代的意思.在技术发展的过程中,HP称这种技术为virtual RAID:NetApp称之为DDP(Dynamic Disk Pool).本质上的思想是相同的,都是通过底层虚拟化的方式使得RAID构建的灵活性大为增加,并且在数据恢复的时候能够