使用HttpClient4.X模拟浏览器登录使用Google Alert(一)

最近使用Google Alert,然后就想自己做点东西,结果悲剧的发现Google Alert居然没有提供API给开发者直接使用.无比蛋疼之余只好尝试着使用HttpClient来模拟浏览器行为进行登录,伪造一份Google Alert API出来使用.

这种方法的好处在于,就程序所获得的信息基本和我们从浏览器看到的信息差不多,问题就在于一旦访问量大了的话,Google会做出反应的。

接下来一步步来简单实现这些功能。

1.第一步我们需要确定,登陆的网页,在这里,Google所有的登录页面最后都会转到https://accounts.google.com/ServiceLogin这个页面或者https://accounts.google.com/ServiceLoginAuth。这个连接后面可能有一大堆的参数比如https://accounts.google.com/ServiceLogin?hl=en&service=alerts&continue=http://www.google.com.sg/alerts/manage,但是可以完全忽略。
有了这个连接我们就可以像浏览器一样发送请求然后返回登录的界面。普通的在浏览器地址栏输入的连接发送的都是GET请求,因此我们使用HttpGet来模拟。

DefaultHttpClient hc = new DefaultHttpClient();
HttpGet request = new HttpGet(url);


此外,浏览器很重要的一个行为就是会在访问中加入HTTP Header,所以我们也需要在访问的连接中加入HTTP Header。至于需要加入什么Header,我们可以通过观察Chrome中的network来了解。



最基本的我们一般会加入ACCEPT, ACCEPT-LANGUAGE, USER-AGENT这些信息。比如添加ACCEPT我们可以用
request.setHeader("Accept","text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8");


设置完HTTP Header我们就可以发送HTTP请求了,发送完请求我们应该会得到服务端给的回复就是Response。
HttpResponse response = hc.execute(request);


但这里得到的还是Response对象,还无法直接获得HTML文件。我们需要借助输入输出流来获得hmtl码。
BufferedReader br = new BufferedReader(new InputStreamReader(response.getEntity().getContent()));


接下来,大家应该很熟悉了,一行一行的读去就行。
StringBuffer result = new StringBuffer();
while((line = br.readLine()) != null){
result.append(line);
}


最后的result.toString()就将输出我们所需要的HTML了。
到这里,so happy, 我们已经提取到了登录页面的HTML码了,剩下的我们就需要获取这个登录页面中的一些登录所需要的信息了。

2.第二,我们需要知道发送登录请求的连接,这个我们可以通过chrome或者firefox中查看得到。



从上图我们可以很清楚的看到,Google的登录不仅仅只是登录用户名和密码,还有许多其他的隐藏信息。这也就是我们为什么需要抓取登录页面的原因,这样我们才能够获取到这些参数。

为了获取这些参数,我们可以手动的去一个一个的找出来,更好的一种方法是使用Jsoup包,使用Jsoup包就和javascript中使用getElementById之类的方法一样,可以很方便的获取HTML中的元素。

Document doc = Jsoup.parse(html);//将纯HTML文本转化成具有结构的Document对象
Element formEl = doc.getElementById("gaia_loginform");//获取登录form
Elements inputs = formEl.getElementsByTag("input");//获取form底下的所有input


除了网页中自带的一些参数,最重要的是用户名和密码,因此如果是用户名或者密码的input,我们不能直接使用默认的value,而是我们指定的value。

for(Element el: inputs) {//loop循环每一个input
    String elName = el.attr("name");//获取input的name属性
    String elValue = el.attr("value");//获取input的value属性
    String elType = el.attr("type");//获取input的type属性
    
    if(elName.equals("Email")) {
        elValue = name;//如果属性名是Email,就将值设置成用户定义的值
    }else if(elName.equals("Passwd")) {
        elValue = word;//如果属性名是Passwd,就将值设置为用户定义的值
    }
    
    if(!elName.equals("button")&&!elType.equals("submit")) {//此外有些button是input应排除
        list.add(new BasicNameValuePair(elName, elValue));//创建键值对加入list
    }
}


以上这段代码返回的list就包含了我们所需要的所有登录的参数了。剩下的我们就需要像之前模拟GET请求一样,模拟浏览器发送POST请求。

和GET请求一样我们需要先创建一个request。这里的url是我们从登录页面上的form action获取的url。
HttpPost request = new HttpPost("https://accounts.google.com/ServiceLoginAuth");


然后同样的设置HTTP Header。
request.setHeader(......);


唯一不同的是,我们需要设置POST附带的参数。这里使用setEntity方法。params是一个List<NameValuePair>。也就是前一段代码中返回的变量list。
request.setEntity(new UrlEncodedFormEntity(params));


设置完参数,就可以发送request然后接收response了。不过这里我们还添加了第二个参数,context,这个context会记录一个请求所需要的一些数据变量,暂时先不用了解,到了后面我们会了解到其用途。
HttpResponse response = hc.execute(request, context);//context 是 HttpContext的对象


这样我们就登录成功了。要想知道是否真的成功了我们可以查看返回的状态码。
int statusCode = response.getStatusLine().getStatusCode();


这里的状态码应该是会返回302,也就是说暂时发生了跳转,这是因为Google跳转到另外的连接进行了认证。这样我们就顺利的完成了登录。

今天就到这里吧,太累了,明天还要继续上班,礼拜五快来吧........过后我们还会继续登录后的操作,这才是登录的意义所在不是。在所有内容之后我会将整个代码放上,所以如果有不明白的,欢迎大家回复讨论,也可以到时看代码了解。
Note:与新浪博客同步

猜你喜欢

转载自cjcrobin.iteye.com/blog/1940748
今日推荐