作者:小邪
鏈接:https://zhuanlan.zhihu.com/p/23017942
來源:知乎
著作權(quán)歸作者所有。商業(yè)轉(zhuǎn)載請聯(lián)系作者獲得授權(quán),非商業(yè)轉(zhuǎn)載請注明出處。
搞了幾年的Android開發(fā)落萎,第一次寫博客,這次就先分享一下用Android手機(jī)端如何模擬登陸知乎(首頁)
1? 抓包
要想實現(xiàn)模擬登錄翩肌,那需要確定一下模擬登錄的網(wǎng)站的登錄邏輯是怎么樣模暗,并且要確定登錄的協(xié)議以及參數(shù)是什么樣的,因此首先要進(jìn)行對該網(wǎng)站進(jìn)行抓包念祭。目前市場上的抓包工具有很多HttpWacth,wireShake等,今天就不先介紹這些工具怎么用了碍侦,就先使用Chrome的開發(fā)者工具進(jìn)行抓包粱坤。首先用Chrome瀏覽器打開知乎網(wǎng)站(首頁),打開開發(fā)者工具,在更多工具中選擇開發(fā)者工具瓷产,選到Network選項站玄,如圖:
使用自己的知乎賬號,登陸知乎,如下圖:
通過抓包的過程中濒旦,我們可以看到株旷,知乎網(wǎng)點擊登錄后,是通過一個Post請求尔邓,那么單擊一下phone_num晾剖,可以看到,請求的URL梯嗽、Header以及參數(shù)齿尽,如下圖:
現(xiàn)在,URL灯节、Header以及參數(shù)都確定了循头,但是參數(shù)中的_xsrf绵估,我們不知道是什么參數(shù),那么查看一下知乎登陸頁面的源代碼卡骂,我們可以看到這么一行:
同時国裳,查看它的源代碼,我們還可以考慮到這個登錄全跨,可能存在驗證碼躏救,因此我們故意輸錯密碼,看看第二次登陸是否有驗證碼螟蒸,以及報什么錯誤盒使,在程序中好處理,抓包方式同上七嫌,在此就不在贅述少办,這個登陸有時候會有驗證碼,鏈接是:
https://www.zhihu.com/captcha.gif?type=login
現(xiàn)在前期抓包工作完成诵原,那么接下來就是如何實現(xiàn)
2 HttpClient+Jsoup實現(xiàn)
首先我們考慮到知乎的網(wǎng)站是HTTPS的英妓,那么我們要讓HttpClient支持HTTPS請求,我采用的是忽略證書的方式绍赛,具體實現(xiàn)方式蔓纠,大家也都能百度到,如果有不會的吗蚌,那么留言一下腿倚,我會整理一下自己的代碼上傳。
然后用Jsoup爬去知乎的頁面蚯妇,獲取_xsrf的值敷燎,并保存Cookie:
public String getZHPager(String url){try {HttpGet get = new HttpGet(url);HttpResponse response = client.execute(get);LogUtil.v("rescode", response.getStatusLine().getStatusCode()+""); cookie=((AbstractHttpClient)client).getCookieStore().getCookies().get(0).getValue();LogUtil.v("cookie", cookie);String str = EntityUtils.toString(response.getEntity(), "UTF-8");LogUtil.v("rescode", response.getStatusLine().getStatusCode()+"");LogUtil.v("re", str);return str;} catch (ClientProtocolException e) {// TODO Auto-generated catch blocke.printStackTrace();} catch (IOException e) {// TODO Auto-generated catch blocke.printStackTrace();}return null;}
public String getHtmlStr(String str){? ? try{Document doc;doc = Jsoup.parse(str);? ? ? ? Elements links = doc.getElementsByTag("input");? ? ? ? for(Element e :links){? if(e.attr("name").toString().equals("_xsrf")){LogUtil.v("_xsrf",e.attr("value").toString());return e.attr("value").toString();? ? ? ? ? ? }? ? ? ? }? ? ? }catch(Exception e){? ? LogUtil.v("_xsrf", e.toString());? ? ? }? return null;}
接下來就是請求,
public String HttpPostData(String username,String password){//long cTime=System.currentTimeMillis();_xsrf = getHtmlStr(getStr(ZhConfig.MainUrl));//Log.v("lt", lt);//client.getParams().setParameter(arg0, arg1)List params = new LinkedList();params.add(new BasicNameValuePair("remember_me","true"));params.add(new BasicNameValuePair("password",password));params.add(new BasicNameValuePair("_eventId","submit"));params.add(new BasicNameValuePair("_xsrf",_xsrf));params.add(new BasicNameValuePair("phone_num",username));HttpPost post = new HttpPost(LoginUrl);try {post.setEntity(new UrlEncodedFormEntity(params, "utf-8"));post.addHeader("Connection", "Keep-Alive");post.addHeader("Content-Type", "application/x-www-form-urlencoded; charset=UTF-8");post.addHeader("Host", "www.zhihu.com");post.addHeader("User-Agent", "Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.1; WOW64; Trident/5.0)");post.addHeader("Referer", "https://www.zhihu.com/");? ? post.getParams().setParameter("http.protocol.allow-circular-redirects", true);//post.addHeader("Cookie","JSESSIONID="+cookie);post.addHeader("Origin", "https://www.zhihu.com");post.getParams().setParameter(? ? "http.protocol.cookie-policy",CookiePolicy.BROWSER_COMPATIBILITY);HttpResponse response = client.execute(post);HttpEntity entity = response.getEntity();InputStream stream = entity.getContent();ByteArrayOutputStream bos=new ByteArrayOutputStream();byte[] buffer=new byte[1024];int len = 0;while((len=stream.read(buffer))!=-1){bos.write(buffer,0,len);}//byte[] dataImage=bos.toByteArray();bos.close();stream.close();//String str = EntityUtils.toString(response.getEntity(), "UTF-8");String str = new String (bos.toByteArray(),"UTF-8");? ? ? ? ? ? ? ? ? ? ? ? Log.v("result",str+"");if(!str.contains("\\u767b\\u5f55\\u6210\\u529f")){return "1";}else{return cookie;}//long tTime=System.currentTimeMillis();//Log.v("TAG", tTime-cTime+"");} catch (UnsupportedEncodingException e) {// TODO Auto-generated catch blocke.printStackTrace();} catch (ClientProtocolException e) {// TODO Auto- generated catch blocke.printStackTrace();} catch (IOException e) {// TODO Auto-generated catch blocke.printStackTrace();}return "";}
其中“ \\u767b\\u5f55\\u6210\\u529f “這個”登陸成功“ 編碼箩言,寫這篇博客時硬贯,還沒有仔細(xì)看它的編碼是什么,大家可以具體看一下陨收,最后注意的一下就是有驗證碼登陸的時候饭豹,就是請求一下驗證碼圖片(如下),登錄時候添加一個參數(shù)params.add(new BasicNameValuePair("captcha", captcha)); 即可务漩。
public Bitmap getLoginYzm(){HttpGet get = new HttpGet(ZhConfig.YZMUrl);get.addHeader("Connection", "Keep-Alive");get.addHeader("Content-Type", "application/x-www-form-urlencoded");get.addHeader("Host", "www.zhihu.com");get.addHeader("User-Agent", "Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.1; WOW64; Trident/5.0)");get.addHeader("Referer", "https://www.zhihu.com/");HttpResponse res;try {res = client.execute(get);HttpEntity entity = res.getEntity();? ? ? ? InputStream in =entity.getContent();? ? ? ? ? ByteArrayOutputStream bos=new ByteArrayOutputStream();? ? ? ? ? byte[] buffer=new byte[1024];? ? ? ? ? int len = 0;? ? ? ? ? while((len=in.read(buffer))!=-1){? ? ? ? ? ? ? bos.write(buffer,0,len);? ? ? ? ? }? ? ? ? ? byte[] dataImage=bos.toByteArray();? ? ? ? ? bos.close();? ? ? ? ? in.close();? ? ? ? ? Bitmap bitmap =BitmapFactory.decodeByteArray(dataImage, 0, dataImage.length);? ? ? ? return bitmap;} catch (ClientProtocolException e) {// TODO Auto-generated catch blocke.printStackTrace();} catch (IOException e) {// TODO Auto-generated catch blocke.printStackTrace();}return null;}