`

用HttpClient抓取人人网高校数据库(省,高校,院系三级级联)--更新1

    博客分类:
  • Java
阅读更多

       更新备注:将src文件改成了一个完整的项目,解压后可以直接导入到Eclipse中去,省去大家配置(项目乱码请改项目属性为GBK)。另外,如果你要登陆人人网 的话,需要申请一个人人网账号。这里提供公用的:\

lei.d0809@gmail.com

java123456

请自行修改RenRenNotify.java 对应的东西。


       首先文章有点长,需要点耐心。这里我是一步一步的做的。。。。比较的细,如果你是代码达人,那你就直接下载代码吧。

      有人说图片看不清,我抱歉,第一次咱的图片不完美,你把图片在浏览器上拖动到新窗口,就可以看到你大图了。

 

 


       需求来源,最近学校的课程项目需要一个省,高校,院系的三级级联的东西,这下麻烦了。全国那么多的高校,而且每一个高校的院系设置又不一样,我们小组只有六个人,而且技术都不咋地,要统计那么多的数据,我们估计这学期就别想完成这个项目了。但是我们知道人人网,开心网,腾讯微博上都要高校的数据库,于是想法就产生了:

     1.要么咱拼人品让他们的技术人员给我们他们的数据库,想法是好的,但是人家不肯呀

     2.要么咱通过某种手段获取他们的数据

今天,咱选择第二种。用到工具有:

EditPlus:小巧好用的文本编辑器,是超越的文本编辑器,不解释,用了就知道

Apanta:这个强烈推荐,用它来写Html,Javascript,Css感觉非常好,而且支持各种各样的Javascript的库,如:

               Jquery,但是我想把他集成到MyEclipse上去,出了一点问题,遗憾,弄的我只能同时开启两个。

HttpAnalyzer:这个是用来抓包用的,无论什么包统统抓,不过只能抓Http协议的包,当年傻,分析飞信协议的时候,

                用这个抓,结果只抓了一点东西。如果你想抓取更底层的推荐一个:WireShark,免费的好用的。

MyEclipse:这个不多说了,弄过J2EE的应该都知道的。

另外就是第三Jar包了,HttpClient 4.01 请到:http://hc.apache.org/downloads.cgi 下载,只要是4版本上的都应该可以,如果是3.1版本的估计你要重新写一些代码,因为4较3还是有很大的改进的。

 

      一般来说,一个网站对访问它内部的东西需要权限的验证的,比如你下载某个网站的东西,他会提示说 只有会员才可以下载,于是乎,这里存在一个session,保存了你的登陆信息也就是你的访问网站内部资源的权限了。人人网估计也不是省油的灯(这里有问题,后面解释),于是我们应该登陆它才能获得访问它内部资源的权限。那么我们首先来抓包分析应该怎么用登陆,于是HttpAnalyzer闪亮登场.

打开HttpAnalyzer,让他开始工作,我们打开浏览器,输入renren.com。第一次咱先不急着登陆。我们随便输入一个账号密码看看:

 

 

 

      我们看到当你输入用户名密码后就将你输入的东西post到:http://www.renren.com/PLogin.do,

其中PostData有四个:email,password,origURL,domain。至于后面的数据是我们刚刚在登陆页面上填写的数据。

我们再来看看它登陆页面的源代码:

 

 

      注意我红色标注的地方:我们注意到,除了我们刚刚在上面发送的数据还有其他的隐藏发送的的东西:例如:origURL等等,这里他们是<input type="hidden" />,应该说在form里面的input都应该发送过去,但是这里他只发送了四个。

既然postdata只有那么四个参数,那我们就姑且只用那个四个东西好了。

所以我们用HttpClient构造请求的时候,就应该将这四个参数的给附带进去,部分代码如下:

// 将要发送的数据封包
  List<NameValuePair> params = new ArrayList<NameValuePair>();
  params.add(new BasicNameValuePair("email", this.email));
  params.add(new BasicNameValuePair("password", this.password));
  params.add(new BasicNameValuePair("origURL", origURL));
  params.add(new BasicNameValuePair("domain", domain));

 

接下来我们来完整登陆一次:

当输入正确的用户名密码,点击登陆,我们又获得什么样的东西呢?参见如下:

 

 

返回的内容意思大概是 地址转变了要进行跳转,而且返回的相应头是 302,文件修改了。再看一下 返回的消息头:

 

 

       有一个Location,应该是要我们跳转的地址。这样我们应该可以访问人人网的任意连接资源了。

 

登录过程的完整代码(包含读嗅探指定资源的链接):

 

import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.util.ArrayList;
import java.util.List;

import org.apache.http.HttpResponse;
import org.apache.http.NameValuePair;
import org.apache.http.client.ClientProtocolException;
import org.apache.http.client.ResponseHandler;
import org.apache.http.client.entity.UrlEncodedFormEntity;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.impl.client.BasicResponseHandler;
import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.http.message.BasicNameValuePair;
import org.apache.http.protocol.HTTP;

/**
 * 
 * 
 * Author : Saitkey < lei_d@foxmail.com >
 */
public class RenRenNotify {
	private static HttpResponse response;
	private static DefaultHttpClient httpClient;

	public RenRenNotify(String userName, String password) {
		this.httpClient = new DefaultHttpClient();
		String loginForm = "http://www.renren.com/PLogin.do";
		String origURL = "http://www.renren.com/Home.do";
		String domain = "renren.com";
		// 在首页表单上是隐藏的 抓包后分析,并没有发送到服务器
		// String autoLogin = "true";
		// 构造一个POST请求,利用Httclient提供的包
		HttpPost httpPost = new HttpPost(loginForm);
		// 将要发送的数据封包
		List<NameValuePair> params = new ArrayList<NameValuePair>();
		params.add(new BasicNameValuePair("email", userName));
		params.add(new BasicNameValuePair("password", password));
		params.add(new BasicNameValuePair("origURL", origURL));
		params.add(new BasicNameValuePair("domain", domain));

		// 封包添加到Post请求
		try {
			httpPost.setEntity(new UrlEncodedFormEntity(params, HTTP.UTF_8));
		} catch (UnsupportedEncodingException e1) {
			// TODO Auto-generated catch block
			e1.printStackTrace();
		}
		// 将 get 和post 方法包含到一个函数里面去,这里就是登陆过程了。
		response = postMethod(httpPost);
		/*
		 * 有跳转 System.out.println(response.getStatusLine());//返回302
		 * Header[]headers=response.getAllHeaders(); for (int i = 0; i <
		 * headers.length; i++) { Header header = headers[i];
		 * System.out.println(header.getName()+": "+header.getValue()); }
		 */
		// 读取跳转的地址
		// String redirectUrl = response.getFirstHeader("Location").getValue();
		// 查看一下跳转过后,都出现哪些内容.
		// response=getMethod(redirectUrl);//函数见后面
		// System.out.println(response.getStatusLine()); // HTTP/1.1 200 OK

		// 读取一下主页都有什么内容 已经登陆进去
		// System.out.println(readHtml("http://www.renren.com/home"));
	}

	// 嗅探指定页面的代码
	public String notify(String url) {
		HttpGet get = new HttpGet(url);
		ResponseHandler<String> responseHandler = new BasicResponseHandler();
		String txt = null;
		try {
			txt = httpClient.execute(get, responseHandler);
		} catch (ClientProtocolException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		} finally {
			get.abort();
		}
		return txt;
	}

	// 用post方法向服务器请求 并获得响应,因为post方法要封装参数,因此在函数外部封装好传参
	public HttpResponse postMethod(HttpPost post) {
		HttpResponse resp = null;
		try {
			resp = httpClient.execute(post);
		} catch (ClientProtocolException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		} finally {
			post.abort();
		}
		return resp;
	}

	// 用get方法向服务器请求 并获得响应
	public HttpResponse getMethod(String url) {
		HttpGet get = new HttpGet(url);
		HttpResponse resp = null;
		try {
			resp = httpClient.execute(get);
		} catch (ClientProtocolException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		} finally {
			get.abort();
		}
		return resp;
	}

	public static void main(String[] args) {
		RenRenNotify notify = new RenRenNotify("[你的用户名]",
				"[你的密码]");
		System.out.println(notify
				.notify("http://www.renren.com/home"));
	}

}

 

 

        好了,现在登录了。我们去修改自己的教育信息吧,首先自然是进入相应的页面:

 

       当我们进入了修改教育信息的时候,我们发现HttpAnalyzer里面多了如下内容:

 

 

 

   注意红色的内容。这里应该是所有高校的信息。体积也达到了402kb,看一下里面的内容:

 

 

 

        这个里面有个奇怪的东西:\u4e2d\u56fd 这个是 “中国”的意思,经过转码了。用JavaScript 直接 alert('u4e2d\u56fd '),就明了了。

        对于一长串的字符,可以用下面的代码进行回来(code是源):

 

 

		StringBuffer sb = new StringBuffer(code);
		int pos;
		while ((pos = sb.indexOf("\\u")) > -1) {
			String tmp = sb.substring(pos, pos + 6);
			sb.replace(pos, pos + 6, Character.toString((char) Integer
					.parseInt(tmp.substring(2), 16)));
		}
		code = sb.toString();

 

 接下来,我们选择一个高校看看,HttpAnalyzer里面出现如下的信息:

 

 

 

 

再来一下:

 

 

 

 

       所以通过上面两次抓取,我们应该得出一个例子,那就是:我们选择好了一个大学,就会相应的得出他的ID,然后这时候会想服务器发送一个请求查询:http://www.renren.com/GetDep.do?id=13003 ,其中id后面的便是高校的代号了。然后返回的是一串html代码,如下:

 

 

 

         这里同样是奇怪的一串数字,这种也是Unicode,不过是十进制的,而且在编码的前后分别加上“&#”和“;”就可以形成Html实体字符,可以在网页上直接显示。

 

 

对于以上的代码,我们也参照上面写一个转换的代码:如下:

 

		StringBuffer sb=new StringBuffer(code);
		int pos;
		while ((pos=sb.indexOf("&#"))>-1) {
			String tmp=sb.substring(pos+2, pos+7);
			sb.replace(pos, pos+8, Character.toString((char)Integer.parseInt(tmp,10)));
		}
		code=sb.toString();

 

        写到这里,我们的工作也做了一大半了。于是乎,我这里不得不跟大家陈清一个事实,获得

http://s.xnimg.cn/a13819/allunivlist.js

http://www.renren.com/GetDep.do?id=13003

的页面代码,人人网是没有设置 session的权限认证的。直接可以读不信你可以点击上面的两个地址,你就发现,原来可以直接读取的。

 

       也就是说。我们可以另辟路径,不用通过HttpClient去登陆一下在取得数据,这一点很不好意思。我刚开始没有意识到。不过,这里你也还是学会了一种登陆一个服务器的办法,说不定以后你会用到呢。

 

 

好了,下面我们开始另一种方法。

       首先,我们对获取http://s.xnimg.cn/a13819/allunivlist.js的数据进行分析一下:

var allUnivList = [{"id":"00","univs":"","name":"\u4e2d\u56fd","provs":[{............."country_id":0,"name":"\u53f0\u6e7e"}]},{"id":"01","univs"...................

这样的数据类型。我想做过ajax的都知道是json类型的。 但是这里我要用Java的正则表达式进行解析。

 

首先分析数据结构:

[{国家:[{省市区[{高校S}],......}],....},....] 大概就是这样的结构 其中....表示可能有多个 同级机构。如 安徽省呵北京市, 而在北京市下有 清华大学和北京大学 是同级的。以此类推啦。

 

我只需要中国的的大学,所以我首先选出中国这块的数据:用到的正则表达式是:"\"provs\":(.*?)]}"

这里主要对比 在台湾省结束的时候,有]}标志,而且在前面并没有出现,而且用非贪婪模式去批判就能保证是中国的高校了。如图

 

 

取得了中国部分,接下来对中国的省市区进行解析了,同样,我们看到:

[{"id":"00",............"country_id":0,"name":"..........."},这样的结构

 

所以对每一个省我们可以分析到如下的正则表达式:id\":(.*?),\"univs\":(.*?),\"country_id\":0,\"name\":\"(.*?)\"}

       然后对 中国这部分进行一个循环,就可以得到中国所有的省市区了,同样我们对每一个省市,要对他们包含的高校进行选择:

 

       我们很容易就可以看到高校的 结构应该是:{"id":1001,"name":"\u6e05\u534e\u5927\u5b66"} 类似,那么正则表达式应该是:"id\":(.*?),\"name\":\"(.*?)\"";

 

       对于每一个高校,我们可以类似于省市那样处理,用循环匹配,就可以得到这个省市的所以高校。但是对于每一个高校。我们要还需要获得他的院系信息。前文跟大家分分析了,院系信息是通过http://www.renren.com/GetDep.do?id=xxxx来动态获取(xxx代表高校的编号),那么我们在抓取高校的时候,顺带也将他们的院系信息获取了。

写了这么多,咱直接上代码:

      你也可以选择下载下面的代码。里面有一些必要的文件已经jar包,需要自己配置一下。如果不会,请留言吧,我争取重新打包再上传上来。

 

import java.io.File;
import java.io.IOException;
import java.io.PrintStream;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import org.apache.http.client.ClientProtocolException;
import org.apache.http.client.HttpClient;
import org.apache.http.client.ResponseHandler;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.impl.client.BasicResponseHandler;
import org.apache.http.impl.client.DefaultHttpClient;

/**
 * 
 * 
 * Author : Saitkey < lei_d@foxmail.com >
 */
public class GenerateSQL {
	// 构建省的sql文件
	private File province = new File("provice.sql");
	// 构建高校的sql文件
	private File college = new File("college.sql");
	// 构建院系的sql文件
	private File department = new File("department.sql");

	GenerateSQL() throws ClientProtocolException, IOException {
		HttpClient client = new DefaultHttpClient();
		ResponseHandler<String> responseHandler = new BasicResponseHandler();
		String depUrl = "http://www.renren.com/GetDep.do?id=";
		String allunivs = "http://s.xnimg.cn/a13819/allunivlist.js";
		HttpGet get = new HttpGet(allunivs);
		System.out.println("读取高校信息...");
		StringBuffer sb = new StringBuffer(client.execute(get, responseHandler));
		System.out.println("读取完成...");

		// 对获取的字符串进行处理截取从"provs":到}]},{"id":"01"部分
		String alluinvRegex = "\"provs\":(.*?)]}";
		Pattern pattern = Pattern.compile(alluinvRegex);
		String chn = "";
		Matcher matcher = pattern.matcher(sb.toString());
		matcher.find();
		chn = matcher.group(1);
		// System.out.println(convertFromHex(tmp));

		// 对截取的中国部分按照省市区进行匹配"id":1,"univs" ...... "country_id":0,"name":"台湾"
		String regex2 = "id\":(.*?),\"univs\":(.*?),\"country_id\":0,\"name\":\"(.*?)\"}";
		Pattern pattern2 = Pattern.compile(regex2);
		Matcher matcher2 = pattern2.matcher(chn);
		StringBuilder provsBuilder = new StringBuilder();
		StringBuilder colBuilder = new StringBuilder();
		StringBuilder deparBuilder = new StringBuilder();
		while (matcher2.find()) {
			// 我们项目的sql语句,如果你们数据库不一样,稍微修改一下拉
			provsBuilder.append("insert into province(PROID,PRONAME)values('"
					+ matcher2.group(1) + "','"
					+ convertFromHex(matcher2.group(3)) + "');\n");
			System.out.println("生成-" + convertFromHex(matcher2.group(3))
					+ "-数据库");
			// 取得学校的ID,还有名字 "id":1001,"name":"\u6e05\u534e\u5927\u5b66"
			String colRegex = "id\":(.*?),\"name\":\"(.*?)\"";
			Pattern colPattern = Pattern.compile(colRegex);
			Matcher colMatcher = colPattern.matcher(matcher2.group(2));
			while (colMatcher.find()) {
				colBuilder
						.append("insert into COLLEGE(PROID,COLID,COLNAME)values('"
								+ matcher2.group(1)
								+ "','"
								+ colMatcher.group(1)
								+ "','"
								+ convertFromHex(colMatcher.group(2)) + "');\n");

				System.out.println("生成-" + convertFromHex(colMatcher.group(2))
						+ "-数据库");

				get = new HttpGet(depUrl + colMatcher.group(1));
				ResponseHandler<String> depHandler = new BasicResponseHandler();
				generateDepartment(client.execute(get, depHandler), colMatcher
						.group(1), deparBuilder);
			}

		}
		PrintStream ps = new PrintStream(province);
		ps.print(provsBuilder.toString());
		ps.close();

		PrintStream ps2 = new PrintStream(college);
		ps2.print(colBuilder.toString());
		ps2.close();

		PrintStream ps3 = new PrintStream(department);
		ps3.print(deparBuilder.toString());
		ps3.close();
		System.err.println("\n\n\n完成数据库生成,请打开项目目录查看!");
	}

	// 这个函数用来处理行查询到的高校院系 <option
	// value='&#20013;&#22269;&#35821;&#35328;&#25991;&#23398;&#23398;&#38498;'>&#20013;&#22269;&#35821;&#35328;&#25991;&#23398;&#23398;&#38498;</option>
	public void generateDepartment(String src, String colid, StringBuilder sb) {
		String departRegex = "value='(.+?)'>";// 开始用这个正则表达式"value='(.*?)'>";
		// 后来发现有问题,问题你自己探索吧。
		Pattern pattern = Pattern.compile(departRegex);
		Matcher matcher = pattern.matcher(src);
		while (matcher.find()) {
			sb.append("insert into DEPARTMENT(COLID,DEPNAME)values('" + colid
					+ "','" + convertFromDec(matcher.group(1)) + "');\n");
		}
	}

	public static String convertDec(String src) {
		return Character.toString((char) Integer.parseInt(src, 10));
	}

	public static String convertHex(String src) {
		return Character
				.toString((char) Integer.parseInt(src.substring(2), 16));
	}

	// 转换&#xxxxx;形式Unicode
	private String convertFromDec(String code) {
		StringBuffer sb = new StringBuffer(code);
		int startPos;
		int endPos;
		while ((startPos = sb.indexOf("&#")) > -1) {
			endPos = sb.indexOf(";");
			String tmp = sb.substring(startPos + 2, endPos);
			sb.replace(startPos, endPos + 1, Character.toString((char) Integer
					.parseInt(tmp, 10)));
		}
		return code = sb.toString();
	}

	// 转换16进制的Unicode,
	private String convertFromHex(String code) {
		StringBuffer sb = new StringBuffer(code);
		int pos;
		while ((pos = sb.indexOf("\\u")) > -1) {
			String tmp = sb.substring(pos, pos + 6);
			sb.replace(pos, pos + 6, Character.toString((char) Integer
					.parseInt(tmp.substring(2), 16)));
		}
		return code = sb.toString();
	}

	public static void main(String[] args) throws ClientProtocolException,
			IOException {
		new GenerateSQL();
	}
}

 

      写到这里,基本上完成了高校数据库的抓取工作,现在只需要导入刚刚生成的sql文件就可以了。如果你想抓取其他的信息。原理也应该差不多的吧。只不过要看看他们有没有设置session 的权限认证了。如果有,那你得写一个登陆的东西获得那认证,前面也写了差不多。应该可以看懂的。感谢你花这么长的时间。

       至于标题的 省 高校 院系级联,好吧, 我骗你了。只不过今天就到此了,还有Asp.net的任务。有了数据库了,咱还怕写不出来那个级联么?各位看官,如果你要什么好的级联,可以分享一下吧。

 

声明:抓取人人网数据仅供学习之用,不对人人网有任何恶意的行为。

  • 大小: 25.6 KB
  • 大小: 58.7 KB
  • 大小: 43.1 KB
  • 大小: 69.6 KB
  • 大小: 25.8 KB
  • 大小: 13.6 KB
  • 大小: 50.2 KB
  • 大小: 40.4 KB
  • 大小: 43.6 KB
  • 大小: 8.4 KB
  • 大小: 5.3 KB
分享到:
评论
74 楼 a1439226817 2014-11-27  
我怎么感觉这个代码就是在解析那个js?
73 楼 a1439226817 2014-11-27  
能否加qq交流一下1439226817
72 楼 w156445045 2014-07-31  
有没有 省--》市--》高校-->院系相关的信息啊 谢谢。
71 楼 sunzhenya 2013-04-18  
ffgfgfg
70 楼 nocb 2011-10-13  
看完了所有的回复,感觉楼主还是比较谦虚的 ,
有所得 谢谢!
69 楼 Javaloverlover 2011-09-28  
不错不错,学习了
68 楼 pywepe 2011-06-18  
firebug
67 楼 guimingyue 2011-01-01  
杯具呀!直接,用楼主的代码,然后用Hibernate插入到数据库,College的主键是autoincrement的,看着只有3000多个数据,然后看看楼主代码中生成的sql中,有3W多,以为生成的有错误,搞了半天,现在发现,楼主代码生成的sql中竟然数字是断断续续的....怪自己....
66 楼 yang02301 2010-12-05  
satikey 写道
yang02301 写道

上传中国和世界大学院校列表(数据取自qq微薄)

上传中国大学院校所含院系列表(数据取自qq微薄)



呵呵。那我做第一个下载的观众了。


不知道大家还有什么资料需要从网上搜刮的,先提出来,看看我能否做到.


65 楼 satikey 2010-12-05  
yang02301 写道

上传中国和世界大学院校列表(数据取自qq微薄)

上传中国大学院校所含院系列表(数据取自qq微薄)



呵呵。那我做第一个下载的观众了。
64 楼 yang02301 2010-12-05  

上传中国和世界大学院校列表(数据取自qq微薄)

上传中国大学院校所含院系列表(数据取自qq微薄)
63 楼 yang02301 2010-12-03  
yang02301 写道
我已经将它搞定。


输出得那叫一个爽。


中国所有城市:
===========
北京
   东城区
      东城区
   西城区
      西城区
   崇文区
      崇文区
   宣武区
      宣武区
   朝阳区
      朝阳区
   丰台区
      丰台区
   石景山区
      石景山区
   海淀区
      海淀区
   门头沟区
      门头沟区
   房山区
      房山区
   通州区
      通州区
   顺义区
      顺义区
   昌平区
      昌平区
   大兴区
      大兴区
   怀柔区
      怀柔区
   平谷区
      平谷区
   密云县
      密云县
   延庆县
      延庆县
天津
   和平区
      和平区
   河东区
      河东区
   河西区
      河西区
   南开区
      南开区
   河北区
      河北区
   红桥区
      红桥区
   塘沽区
      塘沽区
   汉沽区
      汉沽区
   大港区
      大港区
   东丽区
      东丽区
   西青区
      西青区
   津南区
      津南区
   北辰区
      北辰区
   武清区
      武清区
   宝坻区
      宝坻区
   宁河县
      宁河县
   静海县
      静海县
   蓟县
      蓟县
河北
   石家庄
      长安区
      桥东区
      桥西区
      新华区
      井陉矿区
      裕华区
      井陉县
      正定县
      栾城县
      行唐县
      灵寿县
      高邑县
      深泽县
      赞皇县
      无极县
      平山县
      元氏县
      赵县
      辛集市
      藁城市
      晋州市
      新乐市
      鹿泉市
   唐山
      路南区
      路北区
      古冶区
      开平区
      丰南区
      丰润区
      滦县
      滦南县
      乐亭县
      迁西县
      玉田县
      唐海县
      遵化市
      迁安市
   秦皇岛
      海港区
      山海关区
      北戴河区
      青龙满族自治县
      昌黎县
      抚宁县
      卢龙县
   邯郸
      邯山区
      丛台区
      复兴区
      峰峰矿区
      邯郸县
      临漳县
      成安县
      大名县
      涉县
      磁县
      肥乡县
      永年县
      邱县
      鸡泽县
      广平县
      馆陶县
      魏县
      曲周县
      武安市
   邢台
      桥东区
      桥西区
      邢台县
      临城县
      内丘县
      柏乡县
      隆尧县
      任县
      南和县
      宁晋县
      巨鹿县
      新河县
      广宗县
      平乡县
      威县
      清河县
      临西县
      南宫市
      沙河市
   保定
      新市区
      北市区
      南市区
      满城县
      清苑县
      涞水县
      阜平县
      徐水县
      定兴县
      唐县
      高阳县
      容城县
      涞源县
      望都县
      安新县
      易县
      曲阳县
      蠡县
      顺平县
      博野县
      雄县
      涿州市
      定州市
      安国市
      高碑店市
   张家口
      桥东区
      桥西区
      宣化区
      下花园区
      宣化县
      张北县
      康保县
      沽源县
      尚义县
      蔚县
      阳原县
      怀安县
      万全县
      怀来县
      涿鹿县
      赤城县
      崇礼县
   承德
      双桥区
      双滦区
      鹰手营子矿区
      承德县
      兴隆县
      平泉县
      滦平县
      隆化县
      丰宁满族自治县
      宽城满族自治县
      围场满族蒙古族自治县

62 楼 yang02301 2010-12-03  
yang02301 写道
我已经将它搞定。


输出得那叫一个爽。


世界所有国家:
===========
中国
   北京
      东城
      西城
      崇文
      宣武
      朝阳
      丰台
      石景山
      海淀
      门头沟
      房山
      通州
      顺义
      昌平
      大兴
      平谷
      怀柔
      密云
      延庆
   天津
      和平
      河东
      河西
      南开
      河北
      红桥
      塘沽
      汉沽
      大港
      东丽

土耳其
   <没有定义>
      阿达纳
      阿德亚曼
      阿菲永
      阿勒
      阿克萨赖
      阿马西亚
      安卡拉
      安塔利亚
      阿尔达罕
      阿尔特温
      艾登
      巴勒克埃西尔
      巴尔腾
      巴特曼
      巴伊布尔特
      比莱吉克
      宾格尔
      比特利斯
      博卢
      布尔杜尔
      布尔萨
      恰纳卡莱
      昌克勒
      乔鲁姆
      代尼兹利
      迪亚巴克尔
      埃迪尔内
      埃拉泽
      埃斯基谢希尔
      埃尔津詹
      埃尔祖鲁姆
      加济安泰普
      吉雷松
      居米什哈内
      哈卡里
      哈塔伊
      伊切尔
      伊迪尔
      伊斯帕尔塔
      伊斯坦布尔
      伊兹密尔
      卡赫拉曼马拉什
      卡斯塔莫努
      开塞利
      柯克拉雷利
      基利斯
      科贾埃利
      科尼亚
      卡拉比克
      克尔谢希尔
      克勒克卡莱
      卡拉曼
      卡尔斯
      屈塔希亚
      马拉蒂亚
      马尼萨
      马尔丁
      穆拉
(超长无法显示)
61 楼 yang02301 2010-12-03  
我已经将它搞定。


输出得那叫一个爽。
60 楼 satikey 2010-12-02  
yang02301 写道

请高手添加一段代码,从http://mat1.gtimg.com/www/mb/js/mi.City_100831.js导入JSON源数据到Java变量中。

拜托!



我不熟悉 Json数据到Java变量。上次准备弄,因为其他事情耽搁了。
59 楼 yang02301 2010-12-02  
请高手添加一段代码,从http://mat1.gtimg.com/www/mb/js/mi.City_100831.js导入JSON源数据到Java变量中。

http://mat1.gtimg.com/www/mb/js/mi.City_100831.js使用UTF-8编码。

拜托!
58 楼 satikey 2010-12-02  
yang02301 写道


已经搞定,可以自动LOGON,保存Cookies,Redirect URL,得到“高校”列表,得到“院系”列表部分还没有做,应该非常容易的啦,感谢LZ开阔思维!

在发送GET得到“高校”列表时,应该注意造一个请求头,假装使用浏览器。

请LZ在做一个简单的图形码验证LOGON例子,使用QQ所采用的。

最后附上源码,后增加的部分还没有整理,有些乱,请多多包含。



import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.util.ArrayList;
import java.util.List;
import java.util.logging.Level;
import java.util.logging.Logger;
import org.apache.http.Header;

import org.apache.http.HttpResponse;
import org.apache.http.NameValuePair;
import org.apache.http.client.ClientProtocolException;
import org.apache.http.client.ResponseHandler;
import org.apache.http.client.entity.UrlEncodedFormEntity;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.impl.client.BasicResponseHandler;
import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.http.message.BasicNameValuePair;
import org.apache.http.protocol.HTTP;
import java.security.*;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.Set;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import org.apache.http.cookie.Cookie;

public class QQNotify {

    private static HttpResponse response;
    private static DefaultHttpClient httpClient;
    private static Map<String, String> cookies = new HashMap<String, String>();

    public static void main(String[] args) {
        String username = "your username";
        String password = "your password";
        QQNotify notify = new QQNotify(username, password);

        if (true) {
            return;
        }

//        String code = new String(notify.notify("http://s.xnimg.cn/a13819/allunivlist.js"));
//        // 转换16进制的Unicode,
//        StringBuffer sb = new StringBuffer(code);
//        System.out.println(sb.toString());
//        int pos;
//        while ((pos = sb.indexOf("\\u")) > -1) {
//            String tmp = sb.substring(pos, pos + 6);
//            sb.replace(pos, pos + 6, Character.toString((char) Integer.parseInt(tmp.substring(2), 16)));
//        }
//        code = sb.toString();
//        System.out.println(code);

        ///如果你要看下面代码的效果,你只需要 注释掉上面String code  到 System.out.println(code);
        //转换&#xxxxx;形式Unicode
//		String code = new String(notify
//				.notify("http://www.renren.com/GetDep.do?id=13003"));
//		StringBuffer sb=new StringBuffer(code);
//		int pos;
//		while ((pos=sb.indexOf("&#"))>-1) {
//			String tmp=sb.substring(pos+2, pos+7);
//			sb.replace(pos, pos+8, Character.toString((char)Integer.parseInt(tmp,10)));
//		}
//		code=sb.toString();
//		System.out.println(code);
    }

    public QQNotify(String userName, String password) {
        int i;

        this.httpClient = new DefaultHttpClient();

        Header[] headers;
        String url, sb, verifyCode;

        cookies.clear();

        // Step 1: get verify code
        url = "http://ptlogin2.qq.com/check?uin=@" + userName + "&appid=46000101&r=0.617148618189815";
        sb = notify(url);
        SaveCookies(httpClient.getCookieStore().getCookies());
        i = sb.indexOf("'", 19);
        verifyCode = sb.substring(18, i).toUpperCase();
        System.out.println(sb);
        System.out.println("Verify Code = '" + verifyCode + "'");
        if (!false && verifyCode.length() > 4) {
            System.out.println("It seem you need input graphic verify code manually.");
            System.out.println("Wait a few minutes and try again.");
            System.out.println("Program abort!");
            return;
        }

        // Step 2: logon
        //
        // '!UAK' -> '67E5A3B52AE29D6FC6FAFB1587F8D8F3'
        //
        //String str = MD5_3(password) + "!UAK";
        //System.out.println("str = " + str);
        //System.out.println("MD5 = " + MD5(str));
        String str = MD5_3(password) + verifyCode;

        url = "http://ptlogin2.qq.com/login?u=@"
                + userName + "&p="
                + MD5(str) + "&verifycode="
                + verifyCode + "&low_login_enable=1&low_login_hour=720&aid=46000101&u1=http%3A%2F%2Ft.qq.com&ptredirect=1&h=1&from_ui=1&dumy=&fp=loginerroralert";
        sb = notify(url);
        System.out.println(sb);

        SaveCookies(httpClient.getCookieStore().getCookies());
        PrintCookies();
        /*
ptuiCB('0','0','http://t.qq.com','1','登录成功!');
-------- Cookies begin ---------
Exception in thread "main" java.lang.NullPointerException
 0 : [ptvfsession] = 'a56b05373bffaf65643dbe875a1c9614226d1789c91ddd39134c5289878b087b3f8fd21670efcc430d111b63fa41274f'
 1 : [ptcz] = '06aa93cefb0fec33c298f13fecadb5792b7f7816adb11a5e9423e42cd4456115'
 2 : [skey] = '@na9wdcELd'
 3 : [pt2gguin] = 'o1093457233'
 4 : [lskey] = '00010000a1ac49b4a67ea43dde8d6985bb353584846c27cd4a57d63889c082d45da5540b1f78dc6c9f972099'
 5 : [luin] = 'o1093457233'
 6 : [uin] = 'o1093457233'
 7 : [ptuserinfo] = '6864726976653230'
 8 : [ptisp] = ''
-------- Cookies end ---------
-------- Cookies begin ---------
 0 : [ptvfsession] = 'cbebb4c13f69aaca9dabea361c77de60d0fb02bd9991902a7dc5abd486770613746651e4bbd99faebef2b77466e4649b'
 1 : [ptcz] = 'bf9bd2ac71844eae57221a750a7f5321f4e12bdcb0d7178d654160d175da7f3a'
 2 : [skey] = '@na9wdcELd'
 3 : [pt2gguin] = 'o1093457233'
 4 : [lskey] = '00010000035cf86f252e61d9e8f07aa2c39335e2890f01a2863caaffdb4d9e1aa64f2064ec518ccd9772d333'
 5 : [luin] = 'o1093457233'
 6 : [uin] = 'o1093457233'
 7 : [ptuserinfo] = '6864726976653230'
 8 : [ptisp] = ''
-------- Cookies end ---------
        */
        if (true) {
            // Now get country city list
            // sample get data
/*
GET /asyn/schoolist.php?type=4&key=%E4%B8%AD%E5%9B%BD_%E5%8C%97%E4%BA%AC&letter=& HTTP/1.1
Accept: *//*
Accept-Language: en-us
Referer: http://t.qq.com/setting_edu.php
Accept-Encoding: gzip, deflate
User-Agent: Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 6.1; Trident/4.0; QQPinyin 730; SLCC2; .NET CLR 2.0.50727; .NET CLR 3.5.30729; .NET CLR 3.0.30729; Media Center PC 6.0)
Host: t.qq.com
Connection: Keep-Alive
Cookie: ptui_loginuin2=hdrive20; mb_reg_from=8; pgv_pvid=9250536308; pgv_flv=10.0; pgv_r_cookie=10113040085471; pt2gguin=o1093457233; ptcz=3ac05d30f3e337e94f4fe93999002a23d31779fc45e7bb8f7d86b7a2e34e548d; o_cookie=1093457233; luin=o1093457233; lskey=00010000a90b1dff0aad30b3b96d163e6118418db84c6da83a219311bcb2ff34758e77cb1e3f57228e0d8522; pgv_info=ssid=s4051841450; verifysession=h0050e18f0403630ce623631bd8e1f0f51760865ce2107df6a4bbd1e10521919986ace31226351179618b6c20640a91a959; ptisp=; uin=o1093457233; skey=@na9wdcELd
p
 tui_loginuin2=hdrive20;
 mb_reg_from=8;
 pgv_pvid=9250536308;
 pgv_flv=10.0;
 pgv_r_cookie=10113040085471;
 pt2gguin=o1093457233;
 ptcz=3ac05d30f3e337e94f4fe93999002a23d31779fc45e7bb8f7d86b7a2e34e548d;
 o_cookie=1093457233;
 luin=o1093457233;
 lskey=00010000a90b1dff0aad30b3b96d163e6118418db84c6da83a219311bcb2ff34758e77cb1e3f57228e0d8522;
 pgv_info=ssid=s4051841450;
 verifysession=h0050e18f0403630ce623631bd8e1f0f51760865ce2107df6a4bbd1e10521919986ace31226351179618b6c20640a91a959;
 ptisp=;
 uin=o1093457233;
 skey=@na9wdcELd
 */

            //String redirectUrl = "http://t.qq.com/setting_edu.php";
            //http://t.qq.com/asyn/schoolist.php?type=4&key=%E4%B8%AD%E5%9B%BD_%E5%8C%97%E4%BA%AC&letter=&
//中国_北京
String redirectUrl = "http://t.qq.com/asyn/schoolist.php?type=4&key=%E4%B8%AD%E5%9B%BD_%E5%8C%97%E4%BA%AC&letter=&";
//美国
//String redirectUrl = "http://t.qq.com/asyn/schoolist.php?type=4&key=%E7%BE%8E%E5%9B%BD&letter=&";
HttpGet get = new HttpGet(redirectUrl);
get.setHeader("Accept", "*/*");
get.setHeader("Accept-Language", "en-us");
get.setHeader("Referer", "http://t.qq.com/setting_edu.php");
get.setHeader("User-Agent", "gzip, deflate");
get.setHeader("Accept-Language", "Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 6.1; Trident/4.0; QQPinyin 730; SLCC2; .NET CLR 2.0.50727; .NET CLR 3.5.30729; .NET CLR 3.0.30729; Media Center PC 6.0)");
get.setHeader("Host", "t.qq.com");
get.setHeader("Connection", "Keep-Alive");
            try {
                sb = httpClient.execute(get, new BasicResponseHandler());
            } catch (IOException ex) {
                Logger.getLogger(QQNotify.class.getName()).log(Level.SEVERE, null, ex);
            }
            //sb = notify(redirectUrl);
            System.out.println(sb);

        String regex2 = "title=\"(.*?)\">";
        Pattern pattern2 = Pattern.compile(regex2);
        Matcher matcher2 = pattern2.matcher(sb);
        while (matcher2.find()) {
            System.out.println(matcher2.group(1));

        }
            System.out.println("Already logon to '" + userName + "' @ t.qq.com successfully.");
            System.out.println("Next you need redirect to http://t.qq.com/setting_edu.php do grap colleg data.");
            System.out.println("Good luck!");
            return;
        }

        return;
        // 读取跳转的地址
        // String redirectUrl = response.getFirstHeader("Location").getValue();
        // 查看一下跳转过后,都出现哪些内容.
        // response=getMethod(redirectUrl);//函数见后面
        // System.out.println(response.getStatusLine()); // HTTP/1.1 200 OK

        // 读取一下主页都有什么内容 已经登陆进去
        // System.out.println(readHtml("http://www.renren.com/home"));
    }

    // 嗅探指定页面的代码
    public String notify(String url) {
        HttpGet get = new HttpGet(url);
        //get.setHeader("User-Agent", "Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 6.1; Trident/4.0; QQPinyin 730; SLCC2; .NET CLR 2.0.50727; .NET CLR 3.5.30729; .NET CLR 3.0.30729; Media Center PC 6.0)");
        ResponseHandler<String> responseHandler = new BasicResponseHandler();
        String txt = null;
        try {
            txt = httpClient.execute(get, responseHandler);
        } catch (ClientProtocolException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            get.abort();
        }
        return txt;
    }

    // 用post方法向服务器请求 并获得响应,因为post方法要封装参数,因此在函数外部封装好传参
    public HttpResponse postMethod(HttpPost post) {
        HttpResponse resp = null;
        try {
            resp = httpClient.execute(post);
        } catch (ClientProtocolException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            post.abort();
        }
        return resp;
    }

    // 用get方法向服务器请求 并获得响应
    public HttpResponse getMethod(String url) {
        HttpGet get = new HttpGet(url);
        HttpResponse resp = null;
        try {
            resp = httpClient.execute(get);
        } catch (ClientProtocolException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            get.abort();
        }
        return resp;
    }

    private String MD5_3(String plainText) {

        StringBuffer buf = new StringBuffer("");

        try {
            MessageDigest md = MessageDigest.getInstance("MD5");

            md.update(plainText.getBytes());

            // first time
            byte b[] = md.digest();

            // Second Time
            b = md.digest(b);

            // Third Time
            b = md.digest(b);

            int i;
            for (int offset = 0; offset < b.length; offset++) {
                i = b[offset];
                if (i < 0) {
                    i += 256;
                }
                if (i < 16) {
                    buf.append("0");
                }
                buf.append(Integer.toHexString(i));
            }
            //System.out.println("32-bit result: " + buf.toString());//32位的加密
            //System.out.println("byte b[].size: " + b.length);
        } catch (NoSuchAlgorithmException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        return buf.toString().toUpperCase();
    }

    private String MD5(String plainText) {

        StringBuffer buf = new StringBuffer("");

        try {
            MessageDigest md = MessageDigest.getInstance("MD5");

            md.update(plainText.getBytes());

            byte b[] = md.digest();

            int i;
            for (int offset = 0; offset < b.length; offset++) {
                i = b[offset];
                if (i < 0) {
                    i += 256;
                }
                if (i < 16) {
                    buf.append("0");
                }
                buf.append(Integer.toHexString(i));
            }
            //System.out.println("32-bit result: " + buf.toString());//32位的加密
            //System.out.println("byte b[].size: " + b.length);
        } catch (NoSuchAlgorithmException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        return buf.toString().toUpperCase();
    }

    private void SaveCookies(List<Cookie> cs) {
        if (cs.isEmpty()) {
            System.out.println("None");
        } else {
            for (int i = 0; i < cs.size(); i++) {
                cookies.put(cs.get(i).getName(), cs.get(i).getValue());
            }
        }
    }

    private void PrintCookies() {

        int i = 0;

        //Get Map in Set interface to get key and value
        Set s = cookies.entrySet();

        //Move next key and value of Map by iterator
        Iterator it = s.iterator();

        System.out.println("-------- Cookies begin ---------");
        while (it.hasNext()) {
            // key=value separator this by Map.Entry to get key and value
            Map.Entry m = (Map.Entry) it.next();
            System.out.println(" " + i++ + " : [" + m.getKey() + "] = '" + m.getValue() + "'");
        }
        System.out.println("-------- Cookies end ---------");
    }
}
//Get Canada School List
//http://t.qq.com/asyn/schoolist.php?type=4&key=%E5%8A%A0%E6%8B%BF%E5%A4%A7&letter=&





厉害,获取高校院系的那部分就很简单了。恩。基本上就是get post请求了。
57 楼 yang02301 2010-12-02  


已经搞定,可以自动LOGON,保存Cookies,Redirect URL,得到“高校”列表,得到“院系”列表部分还没有做,应该非常容易的啦,感谢LZ开阔思维!

在发送GET得到“高校”列表时,应该注意造一个请求头,假装使用浏览器。

请LZ在做一个简单的图形码验证LOGON例子,使用QQ所采用的。

最后附上源码,后增加的部分还没有整理,有些乱,请多多包含。



import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.util.ArrayList;
import java.util.List;
import java.util.logging.Level;
import java.util.logging.Logger;
import org.apache.http.Header;

import org.apache.http.HttpResponse;
import org.apache.http.NameValuePair;
import org.apache.http.client.ClientProtocolException;
import org.apache.http.client.ResponseHandler;
import org.apache.http.client.entity.UrlEncodedFormEntity;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.impl.client.BasicResponseHandler;
import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.http.message.BasicNameValuePair;
import org.apache.http.protocol.HTTP;
import java.security.*;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.Set;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import org.apache.http.cookie.Cookie;

public class QQNotify {

    private static HttpResponse response;
    private static DefaultHttpClient httpClient;
    private static Map<String, String> cookies = new HashMap<String, String>();

    public static void main(String[] args) {
        String username = "your username";
        String password = "your password";
        QQNotify notify = new QQNotify(username, password);

        if (true) {
            return;
        }

//        String code = new String(notify.notify("http://s.xnimg.cn/a13819/allunivlist.js"));
//        // 转换16进制的Unicode,
//        StringBuffer sb = new StringBuffer(code);
//        System.out.println(sb.toString());
//        int pos;
//        while ((pos = sb.indexOf("\\u")) > -1) {
//            String tmp = sb.substring(pos, pos + 6);
//            sb.replace(pos, pos + 6, Character.toString((char) Integer.parseInt(tmp.substring(2), 16)));
//        }
//        code = sb.toString();
//        System.out.println(code);

        ///如果你要看下面代码的效果,你只需要 注释掉上面String code  到 System.out.println(code);
        //转换&#xxxxx;形式Unicode
//		String code = new String(notify
//				.notify("http://www.renren.com/GetDep.do?id=13003"));
//		StringBuffer sb=new StringBuffer(code);
//		int pos;
//		while ((pos=sb.indexOf("&#"))>-1) {
//			String tmp=sb.substring(pos+2, pos+7);
//			sb.replace(pos, pos+8, Character.toString((char)Integer.parseInt(tmp,10)));
//		}
//		code=sb.toString();
//		System.out.println(code);
    }

    public QQNotify(String userName, String password) {
        int i;

        this.httpClient = new DefaultHttpClient();

        Header[] headers;
        String url, sb, verifyCode;

        cookies.clear();

        // Step 1: get verify code
        url = "http://ptlogin2.qq.com/check?uin=@" + userName + "&appid=46000101&r=0.617148618189815";
        sb = notify(url);
        SaveCookies(httpClient.getCookieStore().getCookies());
        i = sb.indexOf("'", 19);
        verifyCode = sb.substring(18, i).toUpperCase();
        System.out.println(sb);
        System.out.println("Verify Code = '" + verifyCode + "'");
        if (!false && verifyCode.length() > 4) {
            System.out.println("It seem you need input graphic verify code manually.");
            System.out.println("Wait a few minutes and try again.");
            System.out.println("Program abort!");
            return;
        }

        // Step 2: logon
        //
        // '!UAK' -> '67E5A3B52AE29D6FC6FAFB1587F8D8F3'
        //
        //String str = MD5_3(password) + "!UAK";
        //System.out.println("str = " + str);
        //System.out.println("MD5 = " + MD5(str));
        String str = MD5_3(password) + verifyCode;

        url = "http://ptlogin2.qq.com/login?u=@"
                + userName + "&p="
                + MD5(str) + "&verifycode="
                + verifyCode + "&low_login_enable=1&low_login_hour=720&aid=46000101&u1=http%3A%2F%2Ft.qq.com&ptredirect=1&h=1&from_ui=1&dumy=&fp=loginerroralert";
        sb = notify(url);
        System.out.println(sb);

        SaveCookies(httpClient.getCookieStore().getCookies());
        PrintCookies();
        /*
ptuiCB('0','0','http://t.qq.com','1','登录成功!');
-------- Cookies begin ---------
Exception in thread "main" java.lang.NullPointerException
 0 : [ptvfsession] = 'a56b05373bffaf65643dbe875a1c9614226d1789c91ddd39134c5289878b087b3f8fd21670efcc430d111b63fa41274f'
 1 : [ptcz] = '06aa93cefb0fec33c298f13fecadb5792b7f7816adb11a5e9423e42cd4456115'
 2 : [skey] = '@na9wdcELd'
 3 : [pt2gguin] = 'o1093457233'
 4 : [lskey] = '00010000a1ac49b4a67ea43dde8d6985bb353584846c27cd4a57d63889c082d45da5540b1f78dc6c9f972099'
 5 : [luin] = 'o1093457233'
 6 : [uin] = 'o1093457233'
 7 : [ptuserinfo] = '6864726976653230'
 8 : [ptisp] = ''
-------- Cookies end ---------
-------- Cookies begin ---------
 0 : [ptvfsession] = 'cbebb4c13f69aaca9dabea361c77de60d0fb02bd9991902a7dc5abd486770613746651e4bbd99faebef2b77466e4649b'
 1 : [ptcz] = 'bf9bd2ac71844eae57221a750a7f5321f4e12bdcb0d7178d654160d175da7f3a'
 2 : [skey] = '@na9wdcELd'
 3 : [pt2gguin] = 'o1093457233'
 4 : [lskey] = '00010000035cf86f252e61d9e8f07aa2c39335e2890f01a2863caaffdb4d9e1aa64f2064ec518ccd9772d333'
 5 : [luin] = 'o1093457233'
 6 : [uin] = 'o1093457233'
 7 : [ptuserinfo] = '6864726976653230'
 8 : [ptisp] = ''
-------- Cookies end ---------
        */
        if (true) {
            // Now get country city list
            // sample get data
/*
GET /asyn/schoolist.php?type=4&key=%E4%B8%AD%E5%9B%BD_%E5%8C%97%E4%BA%AC&letter=& HTTP/1.1
Accept: *//*
Accept-Language: en-us
Referer: http://t.qq.com/setting_edu.php
Accept-Encoding: gzip, deflate
User-Agent: Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 6.1; Trident/4.0; QQPinyin 730; SLCC2; .NET CLR 2.0.50727; .NET CLR 3.5.30729; .NET CLR 3.0.30729; Media Center PC 6.0)
Host: t.qq.com
Connection: Keep-Alive
Cookie: ptui_loginuin2=hdrive20; mb_reg_from=8; pgv_pvid=9250536308; pgv_flv=10.0; pgv_r_cookie=10113040085471; pt2gguin=o1093457233; ptcz=3ac05d30f3e337e94f4fe93999002a23d31779fc45e7bb8f7d86b7a2e34e548d; o_cookie=1093457233; luin=o1093457233; lskey=00010000a90b1dff0aad30b3b96d163e6118418db84c6da83a219311bcb2ff34758e77cb1e3f57228e0d8522; pgv_info=ssid=s4051841450; verifysession=h0050e18f0403630ce623631bd8e1f0f51760865ce2107df6a4bbd1e10521919986ace31226351179618b6c20640a91a959; ptisp=; uin=o1093457233; skey=@na9wdcELd
p
 tui_loginuin2=hdrive20;
 mb_reg_from=8;
 pgv_pvid=9250536308;
 pgv_flv=10.0;
 pgv_r_cookie=10113040085471;
 pt2gguin=o1093457233;
 ptcz=3ac05d30f3e337e94f4fe93999002a23d31779fc45e7bb8f7d86b7a2e34e548d;
 o_cookie=1093457233;
 luin=o1093457233;
 lskey=00010000a90b1dff0aad30b3b96d163e6118418db84c6da83a219311bcb2ff34758e77cb1e3f57228e0d8522;
 pgv_info=ssid=s4051841450;
 verifysession=h0050e18f0403630ce623631bd8e1f0f51760865ce2107df6a4bbd1e10521919986ace31226351179618b6c20640a91a959;
 ptisp=;
 uin=o1093457233;
 skey=@na9wdcELd
 */

            //String redirectUrl = "http://t.qq.com/setting_edu.php";
            //http://t.qq.com/asyn/schoolist.php?type=4&key=%E4%B8%AD%E5%9B%BD_%E5%8C%97%E4%BA%AC&letter=&
//中国_北京
String redirectUrl = "http://t.qq.com/asyn/schoolist.php?type=4&key=%E4%B8%AD%E5%9B%BD_%E5%8C%97%E4%BA%AC&letter=&";
//美国
//String redirectUrl = "http://t.qq.com/asyn/schoolist.php?type=4&key=%E7%BE%8E%E5%9B%BD&letter=&";
HttpGet get = new HttpGet(redirectUrl);
get.setHeader("Accept", "*/*");
get.setHeader("Accept-Language", "en-us");
get.setHeader("Referer", "http://t.qq.com/setting_edu.php");
get.setHeader("User-Agent", "gzip, deflate");
get.setHeader("Accept-Language", "Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 6.1; Trident/4.0; QQPinyin 730; SLCC2; .NET CLR 2.0.50727; .NET CLR 3.5.30729; .NET CLR 3.0.30729; Media Center PC 6.0)");
get.setHeader("Host", "t.qq.com");
get.setHeader("Connection", "Keep-Alive");
            try {
                sb = httpClient.execute(get, new BasicResponseHandler());
            } catch (IOException ex) {
                Logger.getLogger(QQNotify.class.getName()).log(Level.SEVERE, null, ex);
            }
            //sb = notify(redirectUrl);
            System.out.println(sb);

        String regex2 = "title=\"(.*?)\">";
        Pattern pattern2 = Pattern.compile(regex2);
        Matcher matcher2 = pattern2.matcher(sb);
        while (matcher2.find()) {
            System.out.println(matcher2.group(1));

        }
            System.out.println("Already logon to '" + userName + "' @ t.qq.com successfully.");
            System.out.println("Next you need redirect to http://t.qq.com/setting_edu.php do grap colleg data.");
            System.out.println("Good luck!");
            return;
        }

        return;
        // 读取跳转的地址
        // String redirectUrl = response.getFirstHeader("Location").getValue();
        // 查看一下跳转过后,都出现哪些内容.
        // response=getMethod(redirectUrl);//函数见后面
        // System.out.println(response.getStatusLine()); // HTTP/1.1 200 OK

        // 读取一下主页都有什么内容 已经登陆进去
        // System.out.println(readHtml("http://www.renren.com/home"));
    }

    // 嗅探指定页面的代码
    public String notify(String url) {
        HttpGet get = new HttpGet(url);
        //get.setHeader("User-Agent", "Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 6.1; Trident/4.0; QQPinyin 730; SLCC2; .NET CLR 2.0.50727; .NET CLR 3.5.30729; .NET CLR 3.0.30729; Media Center PC 6.0)");
        ResponseHandler<String> responseHandler = new BasicResponseHandler();
        String txt = null;
        try {
            txt = httpClient.execute(get, responseHandler);
        } catch (ClientProtocolException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            get.abort();
        }
        return txt;
    }

    // 用post方法向服务器请求 并获得响应,因为post方法要封装参数,因此在函数外部封装好传参
    public HttpResponse postMethod(HttpPost post) {
        HttpResponse resp = null;
        try {
            resp = httpClient.execute(post);
        } catch (ClientProtocolException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            post.abort();
        }
        return resp;
    }

    // 用get方法向服务器请求 并获得响应
    public HttpResponse getMethod(String url) {
        HttpGet get = new HttpGet(url);
        HttpResponse resp = null;
        try {
            resp = httpClient.execute(get);
        } catch (ClientProtocolException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            get.abort();
        }
        return resp;
    }

    private String MD5_3(String plainText) {

        StringBuffer buf = new StringBuffer("");

        try {
            MessageDigest md = MessageDigest.getInstance("MD5");

            md.update(plainText.getBytes());

            // first time
            byte b[] = md.digest();

            // Second Time
            b = md.digest(b);

            // Third Time
            b = md.digest(b);

            int i;
            for (int offset = 0; offset < b.length; offset++) {
                i = b[offset];
                if (i < 0) {
                    i += 256;
                }
                if (i < 16) {
                    buf.append("0");
                }
                buf.append(Integer.toHexString(i));
            }
            //System.out.println("32-bit result: " + buf.toString());//32位的加密
            //System.out.println("byte b[].size: " + b.length);
        } catch (NoSuchAlgorithmException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        return buf.toString().toUpperCase();
    }

    private String MD5(String plainText) {

        StringBuffer buf = new StringBuffer("");

        try {
            MessageDigest md = MessageDigest.getInstance("MD5");

            md.update(plainText.getBytes());

            byte b[] = md.digest();

            int i;
            for (int offset = 0; offset < b.length; offset++) {
                i = b[offset];
                if (i < 0) {
                    i += 256;
                }
                if (i < 16) {
                    buf.append("0");
                }
                buf.append(Integer.toHexString(i));
            }
            //System.out.println("32-bit result: " + buf.toString());//32位的加密
            //System.out.println("byte b[].size: " + b.length);
        } catch (NoSuchAlgorithmException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        return buf.toString().toUpperCase();
    }

    private void SaveCookies(List<Cookie> cs) {
        if (cs.isEmpty()) {
            System.out.println("None");
        } else {
            for (int i = 0; i < cs.size(); i++) {
                cookies.put(cs.get(i).getName(), cs.get(i).getValue());
            }
        }
    }

    private void PrintCookies() {

        int i = 0;

        //Get Map in Set interface to get key and value
        Set s = cookies.entrySet();

        //Move next key and value of Map by iterator
        Iterator it = s.iterator();

        System.out.println("-------- Cookies begin ---------");
        while (it.hasNext()) {
            // key=value separator this by Map.Entry to get key and value
            Map.Entry m = (Map.Entry) it.next();
            System.out.println(" " + i++ + " : [" + m.getKey() + "] = '" + m.getValue() + "'");
        }
        System.out.println("-------- Cookies end ---------");
    }
}
//Get Canada School List
//http://t.qq.com/asyn/schoolist.php?type=4&key=%E5%8A%A0%E6%8B%BF%E5%A4%A7&letter=&



56 楼 yang02301 2010-12-02  
yang02301 写道
非常有意思,在Break in t.qq.com的时候发现:当连续LOGON账户多次时,页面会出现要求输入图形认证码(显示代码在JavaScript中,当键入password时向主机请求认证码图形,修改主页HTML代码应该可以屏蔽掉),防止机器人大量Sign In,不过已经实现Java自动Logon t.qq.com功能,随后发帖。

请楼主继续支持如何从t.qq.com自动下载“高校”数据部分。


现附上自动Logon到t.qq.com的Java代码,需要修改username和password,继续努力!


import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.util.ArrayList;
import java.util.List;
import org.apache.http.Header;

import org.apache.http.HttpResponse;
import org.apache.http.NameValuePair;
import org.apache.http.client.ClientProtocolException;
import org.apache.http.client.ResponseHandler;
import org.apache.http.client.entity.UrlEncodedFormEntity;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.impl.client.BasicResponseHandler;
import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.http.message.BasicNameValuePair;
import org.apache.http.protocol.HTTP;
import java.security.*;

public class QQNotify {

    private static HttpResponse response;
    private static DefaultHttpClient httpClient;

    public static void main(String[] args) {
        String username = "your username";
        String password = "your password";
        QQNotify notify = new QQNotify(username, password);

        if (true) {
            return;
        }

//        String code = new String(notify.notify("http://s.xnimg.cn/a13819/allunivlist.js"));
//        // 转换16进制的Unicode,
//        StringBuffer sb = new StringBuffer(code);
//        System.out.println(sb.toString());
//        int pos;
//        while ((pos = sb.indexOf("\\u")) > -1) {
//            String tmp = sb.substring(pos, pos + 6);
//            sb.replace(pos, pos + 6, Character.toString((char) Integer.parseInt(tmp.substring(2), 16)));
//        }
//        code = sb.toString();
//        System.out.println(code);

        ///如果你要看下面代码的效果,你只需要 注释掉上面String code  到 System.out.println(code);
        //转换&#xxxxx;形式Unicode
//		String code = new String(notify
//				.notify("http://www.renren.com/GetDep.do?id=13003"));
//		StringBuffer sb=new StringBuffer(code);
//		int pos;
//		while ((pos=sb.indexOf("&#"))>-1) {
//			String tmp=sb.substring(pos+2, pos+7);
//			sb.replace(pos, pos+8, Character.toString((char)Integer.parseInt(tmp,10)));
//		}
//		code=sb.toString();
//		System.out.println(code);
    }

    public QQNotify(String userName, String password) {
        int i;

        this.httpClient = new DefaultHttpClient();

        Header[] headers;
        String url, sb, verifyCode;

        // Step 1: get verify code
        url = "http://ptlogin2.qq.com/check?uin=@" + userName + "&appid=46000101&r=0.617148618189815";
        sb = notify(url);
        i = sb.indexOf("'", 19);
        verifyCode = sb.substring(18, i).toUpperCase();
        System.out.println(sb);
        System.out.println("Verify Code = '" + verifyCode + "'");
        if (!false && verifyCode.length() > 4) {
            System.out.println("It seem you need input graphic verify code manually.");
            System.out.println("Wait a few minutes and try again.");
            System.out.println("Program abort!");
            return;
        }
        
        // Step 2: logon
        //
        // '!UAK' -> '67E5A3B52AE29D6FC6FAFB1587F8D8F3'
        //
        //String str = MD5_3(password) + "!UAK";
        //System.out.println("str = " + str);
        //System.out.println("MD5 = " + MD5(str));
        String str = MD5_3(password) + verifyCode;

        url = "http://ptlogin2.qq.com/login?u=@" +
                userName + "&p=" +
                MD5(str) + "&verifycode=" +
                verifyCode + "&low_login_enable=1&low_login_hour=720&aid=46000101&u1=http%3A%2F%2Ft.qq.com&ptredirect=1&h=1&from_ui=1&dumy=&fp=loginerroralert";
        sb = notify(url);
        System.out.println(sb);
        if (!true) {
            response = getMethod(url);
            System.out.println(response.getStatusLine());//返回302
            headers = response.getAllHeaders();
            for (i = 0; i < headers.length; i++) {
                Header header = headers[i];
                System.out.println(header.getName() + ": " + header.getValue());
            }
            System.out.println("-----------------------------");
        }
        if (true) {
            System.out.println("Already logon to '" + userName + "' @ t.qq.com successfully.");
            System.out.println("Next you need redirect to http://t.qq.com/setting_edu.php, and grap college data.");
            System.out.println("Good luck!");
            return;
        }

        return;
        // 读取跳转的地址
        // String redirectUrl = response.getFirstHeader("Location").getValue();
        // 查看一下跳转过后,都出现哪些内容.
        // response=getMethod(redirectUrl);//函数见后面
        // System.out.println(response.getStatusLine()); // HTTP/1.1 200 OK

        // 读取一下主页都有什么内容 已经登陆进去
        // System.out.println(readHtml("http://www.renren.com/home"));
    }

    // 嗅探指定页面的代码
    public String notify(String url) {
        HttpGet get = new HttpGet(url);
        ResponseHandler<String> responseHandler = new BasicResponseHandler();
        String txt = null;
        try {
            txt = httpClient.execute(get, responseHandler);
        } catch (ClientProtocolException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            get.abort();
        }
        return txt;
    }

    // 用post方法向服务器请求 并获得响应,因为post方法要封装参数,因此在函数外部封装好传参
    public HttpResponse postMethod(HttpPost post) {
        HttpResponse resp = null;
        try {
            resp = httpClient.execute(post);
        } catch (ClientProtocolException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            post.abort();
        }
        return resp;
    }

    // 用get方法向服务器请求 并获得响应
    public HttpResponse getMethod(String url) {
        HttpGet get = new HttpGet(url);
        HttpResponse resp = null;
        try {
            resp = httpClient.execute(get);
        } catch (ClientProtocolException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            get.abort();
        }
        return resp;
    }

    private String MD5_3(String plainText) {

        StringBuffer buf = new StringBuffer("");

        try {
            MessageDigest md = MessageDigest.getInstance("MD5");

            md.update(plainText.getBytes());

            // first time
            byte b[] = md.digest();

            // Second Time
            b = md.digest(b);

            // Third Time
            b = md.digest(b);

            int i;
            for (int offset = 0; offset < b.length; offset++) {
                i = b[offset];
                if (i < 0) {
                    i += 256;
                }
                if (i < 16) {
                    buf.append("0");
                }
                buf.append(Integer.toHexString(i));
            }
            //System.out.println("32-bit result: " + buf.toString());//32位的加密
            //System.out.println("byte b[].size: " + b.length);
        } catch (NoSuchAlgorithmException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        return buf.toString().toUpperCase();
    }

    private String MD5(String plainText) {

        StringBuffer buf = new StringBuffer("");

        try {
            MessageDigest md = MessageDigest.getInstance("MD5");

            md.update(plainText.getBytes());

            byte b[] = md.digest();

            int i;
            for (int offset = 0; offset < b.length; offset++) {
                i = b[offset];
                if (i < 0) {
                    i += 256;
                }
                if (i < 16) {
                    buf.append("0");
                }
                buf.append(Integer.toHexString(i));
            }
            //System.out.println("32-bit result: " + buf.toString());//32位的加密
            //System.out.println("byte b[].size: " + b.length);
        } catch (NoSuchAlgorithmException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        return buf.toString().toUpperCase();
    }
}





55 楼 yang02301 2010-12-02  
非常有意思,在Break in t.qq.com的时候发现:当连续LOGON账户多次时,页面会出现要求输入图形认证码(显示代码在JavaScript中,当键入password时向主机请求认证码图形,修改主页HTML代码应该可以屏蔽掉),防止机器人大量Sign In,不过已经实现Java自动Logon t.qq.com功能,随后发帖。

请楼主继续支持如何从t.qq.com自动下载“高校”数据部分。

相关推荐

Global site tag (gtag.js) - Google Analytics