使用HttpClient 4.x登陆带有验证码的网站
来源:互联网 发布:3306端口入侵教程 编辑:程序博客网 时间:2024/06/05 00:51
对于爬虫来说,验证码通常是实现过程中的一个巨大的障碍,因为验证码的多样性,有的甚至变态至极,所有一般来说使用代码自动识别验证码是非常困难的,本问的内容就是讲如何将验证码保存到本地,然后通过人工输入验证码实现登陆,从而抓取网页信息。
首先说说整个登陆的流程,当我们打开一个网站的时候,浏览器就会记录该网站的cookie,用于识别信息,同时服务器会向浏览器发送一张验证码的图片,并与该cookie的信息是相关联的,并以此识别用户,然后post提交数据的时候一同提交就实现认证登陆了。
以下登陆我们学校的教务处作为例子,这是我们教务处的登陆界面。
右键打开chrome的审查元素,跟踪到验证码的链接。
很明显"http://218.7.49.34/validateCodeAction.do?random=0.9378238802310079”,就是验证码的链接,其中中有个random=xxxxxxxxxxxxxxxxxxxxxxx的参数,实际上这个参数对于我们获取验证码和登陆是无关的,它只是为了防止浏览器把验证码页面缓存。其实“http://218.7.49.34/validateCodeAction.do”这样也是能获取验证码的,并且每次刷新都能得到不同的验证码,或者在“?random="后面个任意参数都能得到验证码,如图
我最开始就以为random后面的那个数字是与登陆的信息相关了,导致我差点中途放弃,幸好后面遇到大神指点。在代码执行的过程中,首次打开登陆的页面,同时已经伴随着一张验证码的下载,因为在代码中一次无法同时访问两个链接,一个是登陆登陆页面的地址,一个是验证码的地址,所有我们在实际代码中应该先使用httpclient打开登陆的链接,这时httpclient会保存网站的cookie信息,所以我们在执行一次验证码的获取链接就能抓取到验证码了,然后保存到本地文件,输入其内容就能登陆网站了,
然后我们用浏览器登陆一次,查看post请求中到底向服务器发送了那些数据,然后在代码中构造这些参数发送给服务器,模拟登陆,以下是我登陆我的账号显示的信息:
这里写了一个client类,封装了打开网站,获取验证码和登陆功能,
public class Client { private String accout; private String password; HttpClient client = HttpClients.createDefault();//实例化httpclient HttpResponse response = null; String rawHtml; public Client(String accout, String password) { super(); this.accout = accout; this.password = password; } public boolean login() { HttpGet getLoginPage = new HttpGet("http://218.7.49.34/loginAction.do");//教务处登陆页面get try { //打开教务处 client.execute(getLoginPage); //获取验证码 getVerifyingCode(client); //提醒用户并输入验证码 System.out.println("verifying code has been save as verifyCode.jpeg, input its content"); String code; Scanner in = new Scanner(System.in); code = in.nextLine(); in.close(); //设定post参数,和上图中的内容一致 ArrayList<NameValuePair> postData = new ArrayList<NameValuePair>(); postData.add(new BasicNameValuePair("zjh1", "")); postData.add(new BasicNameValuePair("tips", "")); postData.add(new BasicNameValuePair("lx", "")); postData.add(new BasicNameValuePair("eflag", "")); postData.add(new BasicNameValuePair("fs", "")); postData.add(new BasicNameValuePair("dzslh", "")); postData.add(new BasicNameValuePair("zjh", accout));//学号 postData.add(new BasicNameValuePair("mm", password));//密码 postData.add(new BasicNameValuePair("v_yzm", code));//验证码 HttpPost post = new HttpPost("http://218.7.49.34/loginAction.do");//构建post对象 post.setEntity(new UrlEncodedFormEntity(postData));//捆绑参数 response = client.execute(post);//执行登陆行为 rawHtml = EntityUtils.toString(response.getEntity(), "utf-8"); System.out.println(rawHtml); } catch (ClientProtocolException e) { System.out.println(e.getMessage()); } catch (IOException e) { System.out.println(e.getMessage()); } } void getVerifyingCode(HttpClient client) { HttpGet getVerifyCode = new HttpGet("http://218.7.49.34/validateCodeAction.do");//验证码get FileOutputStream fileOutputStream = null; HttpResponse response; try { response = client.execute(getVerifyCode);//获取验证码 /*验证码写入文件,当前工程的根目录,保存为verifyCode.jped*/ fileOutputStream = new FileOutputStream(new File("verifyCode.jpeg")); response.getEntity().writeTo(fileOutputStream); } catch (ClientProtocolException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } finally { try { fileOutputStream.close(); } catch (IOException e) { e.printStackTrace(); } } } }
public class Main {public static void main(String[] args) {Client client = new Client("学号", "密码");client.login();}}
可以对比,下载的信息和浏览器得到的代码是一致的,说明我们已经登陆成功了,最核心的过程已经完成,然后就可以抓取网站上其他的信息了,使用httpget加上目标信息的URL即可抓取。
注意,最好将httpclient相关的操作单独写为类,并且没个功能单独实现,以httpclient作为传递参数,否则第二次执行请求是会出错。
- 使用HttpClient 4.x登陆带有验证码的网站
- Android 中如何使用带有验证码的方式登陆
- HttpClient带验证码登陆
- php实现Ajax带有验证码的登陆注册功能
- PHP使用CURL对带有验证码的网站进行模拟登录
- 使用HttpClient登陆网站 抓取页面数据
- IWebBrowser2登陆网站(无验证码的)
- Java登陆带验证码的网站
- HttpClient4登陆有验证码的网站
- 带有验证码的网站的注册功能
- HttpClient 抓包实现验证码登陆,网站是教务系统
- httpclient绕过登陆验证码抓取数据
- 使用PYTHON登陆验证网站的几种方式!
- vb.net如何使用HttpWebRequest模拟登陆带验证码的网站
- 网页版的模拟登陆有验证码的网站
- Android模拟登陆带验证码的网站客户端
- android 模拟浏览器登陆带验证码的网站
- Android模拟登陆带验证码的网站客户端
- (9.1.1)线性代数之行列式
- 一个有趣的多线程问题
- 浏览器开发系列第二篇:如何编译最新chromium源码
- HTML5
- 开发工具之Eclipse快捷键
- 使用HttpClient 4.x登陆带有验证码的网站
- Memcache 持久性分布式数据库MemcacheDB
- ZOJ 1001
- C# XML序列化去掉XML默认的命名空间及声明头
- 最近对问题(分治法)
- MapWinGIS4.9.3的二次开发
- 在Azure 环境里安装 SharePoint 2013 系统(四)安装、配置SharePoint 2013
- C#创建datatable
- JAVA-ADT:Failed to load the JNI shared library完美解决