您的位置:首页 > 理论基础 > 计算机网络

HttpClient使用第一弹,多线程+IP代理扫描未注册域名

2015-11-08 21:29 1351 查看
一、简介

  HTTP 协议可能是现在 Internet 上使用得最多、最重要的协议了,越来越多的 Java 应用程序需要直接通过 HTTP 协议来访问网络资源。虽然在 JDK 的 java net包中已经提供了访问 HTTP 协议的基本功能,但是对于大部分应用程序来说,JDK 库本身提供的功能还不够丰富和灵活。HttpClient 是 Apache Jakarta Common 下的子项目,用来提供高效的、最新的、功能丰富的支持 HTTP 协议的客户端编程工具包,并且它支持 HTTP 协议最新的版本和建议。HttpClient 已经应用在很多的项目中,比如 Apache Jakarta 上很著名的另外两个开源项目 Cactus 和 HTMLUnit 都使用了 HttpClient。现在HttpClient最新版本为 HttpClient 4.5 (GA) (2015-09-11)

二、准备工作

  通过搜索我们得到查询域名是否注册的万网官方API接口http://panda.www.net.cn/cgi-bin/check.cgi?area_domain=。通过测试,我们得到返回xml值

<?xml version="1.0" encoding="gb2312"?>
<property>
<returncode>200</returncode>
<key>baidu.com</key>
<original>211 : Domain exists</original>
</property>


返回 XML 结果说明:

returncode=200 表示接口返回成功

key=***.com表示当前check的域名

original=210 : Domain name is available 表示域名可以注册

original=211"" : Domain name is not available 表示域名已经注册

original=212 : Domain name is invalid 表示域名参数传输错误

三、编写代码

  首先我们要从本地读取拼音并组装成需要的域名(也可以用英文字母组合,这个可以自行发挥,这里使用两拼拼音进行组合)

1  //存放从文件中读取到的原始字符
2  ArrayList<String> pinyin = new ArrayList<String>();
//这里用队列来存放组合好的域名
ArrayBlockingQueue<String> taskQueue = new ArrayBlockingQueue<String>(163620);
//读取硬盘上的文件
BufferedReader reader = new BufferedReader(new FileReader("E:\\拼音.txt"));
String str;
while(( str=reader.readLine() )!= null){
pinyin.add(str);
}
reader.close();
//组合域名
for(String pinyin1 : pinyin){
for(String pinyin2 : pinyin){
taskQueue.add(pinyin1+pinyin2+domainNameSuffix);//domainNameSuffix是指域名后缀
}
}


经过组合我们得到大约15万个域名,单个线程就显得效率略微低下,如果是同一个ip发送大量请求到万网……几分钟就把你ip禁封了,所以迫不得已要使用代理IP进行访问。

package cn.dsx.ali;

import java.io.BufferedWriter;
import java.io.FileWriter;
import java.io.IOException;
import java.util.concurrent.ArrayBlockingQueue;
import org.apache.http.HttpHost;
import org.apache.http.client.config.RequestConfig;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.protocol.HttpClientContext;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.util.EntityUtils;
import cn.dsx.utils.HttpUtils;

public class DomainRunner implements Runnable {
private CloseableHttpClient httpClient;                //模拟客户端
private CloseableHttpResponse response;                //返回
private String domain,uri="http://panda.www.net.cn/cgi-bin/check.cgi?area_domain=";
private ArrayBlockingQueue<String> taskQueue;        //存储测试的域名
private String ip[];                                //存放IP的数组
private int size;                                    //IP的个数
private int index;                                    //要使用的IP下标
/**
* 初始化
* @param taskQueue 域名队列
* @param ip
*/
public DomainRunner(ArrayBlockingQueue<String> taskQueue, String[] ip){
httpClient = HttpClients.createDefault();
this.taskQueue = taskQueue;
index = size = ip.length;
this.ip = ip;
}

@Override
public void run() {
while(( domain=taskQueue.poll() ) != null){
HttpGet get = null;
try {
get = new HttpGet(uri+domain);
HttpClientContext context = HttpClientContext.create();
get.setHeader("Connection", "close");
//循环取得IP
index--;
if(index<=0){
index = size;
}
//分割出IP和端口
String []str = ip[index].split(":");
HttpHost proxy = new HttpHost(str[0], Integer.parseInt(str[1]));
//设置请求延迟和代理IP
RequestConfig config = RequestConfig.custom()
.setProxy(proxy)
.setSocketTimeout(3000)
.setConnectTimeout(3000)
.build();
get.setConfig(config);
//发送请求
response = httpClient.execute(get,context);
int status = response.getStatusLine().getStatusCode();

if (status >= 200 && status < 300) {
String resultXml = EntityUtils.toString(response.getEntity(),"gb2312");

if(resultXml.contains("<original>210")){
//以追加的形式写入
BufferedWriter writer = new BufferedWriter(new FileWriter("E:\\domain.txt",true));
resultXml = HttpUtils.myRegex("<key>.*?</key>", resultXml).get(0);
resultXml = HttpUtils.mid(resultXml, "<key>", "</key>");
System.err.println(Thread.currentThread().getName()+"未注册"+resultXml);
writer.write(resultXml);
writer.newLine();
writer.flush();
writer.close();
} else if(resultXml.contains("<original>211")   || resultXml.contains("<original>212")  || resultXml.contains("<original>214")){
System.out.println(Thread.currentThread().getName()+"已注册"+domain);
} else {
System.out.println(Thread.currentThread().getName()+"恭喜你中奖了,"+str[0]+"被封");
}
} else {
System.out.println(domain + "验证错误");
}
} catch (Exception e) {
System.err.println(Thread.currentThread().getName()+"异常");
//如果产生异常则代表没有成功发送请求,而domain已经出栈,所以要重新压栈。
taskQueue.add(domain);
} finally{
//必须释放掉资源,不然Booming~
try {
get.releaseConnection();
if (response != null) {
response.close();
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
}


在上面这个类中还用到了我写的一个HttpUtils工具类,其实这个工具类很简单,这里只用到了里面的两个方法。

package cn.dsx.utils;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import org.apache.http.HttpEntity;
import org.apache.http.client.entity.UrlEncodedFormEntity;
import org.apache.http.message.BasicNameValuePair;

/**
* Http相关处理的类
*/
public class HttpUtils {

/**
* map转换成entity
* @param map 待处理的
* @return 处理后的数据
*/
public static HttpEntity mapToEntity(HashMap<String,String> map) throws Exception{
BasicNameValuePair pair = null;
List<BasicNameValuePair> params = new ArrayList<BasicNameValuePair>();
for(Map.Entry<String, String> m : map.entrySet()){
pair = new BasicNameValuePair(m.getKey(),m.getValue());
params.add(pair);
}
HttpEntity entity = new UrlEncodedFormEntity(params,"UTF-8");
return entity;
}

/**
* 取文本之间的字符串
* @param string 源字符串
* @param start 开始字符串
* @param end 结束字符串
* @return 成功返回中间子串,失败返回null
*/
public static String mid(String string, String start, String end) {
int s = string.indexOf(start) + start.length();
int e = string.indexOf(end, s);
if (s > 0 && e > s)
return string.substring(s, e);
return null;
}

/**
*
* @param regex 正则表达式
* @param input 待匹配的字符串
* @return 返回的是匹配的list集合(可能由于正则表达式的不同有多条记录)
*/
public static ArrayList<String> myRegex(String regex, String input) {
ArrayList<String> list = new ArrayList<String>();
Pattern p = Pattern.compile(regex);
Matcher m = p.matcher(input);
while (m.find()) {
list.add(m.group());
}
return list;
}

}


接着我们开启多个线程进行访问

//开启线程
DomainRunner runner = new DomainRunner(taskQueue,ip);
ExecutorService threadPool = Executors.newFixedThreadPool(threadNum);
for(int i=1; i<=threadNum; i++){
System.err.println("线程"+i+"开启。");
threadPool.execute(runner);
}
threadPool.shutdownNow();


最后我们编写一个测试方法

public static void main(String args[]){
String ip[] = {    "58.214.5.229:80","58.220.2.132:80",
"58.220.2.133:80","58.220.2.134:80",
"58.220.2.135:80","58.220.2.136:80",
"58.220.2.137:80","58.220.2.138:80",
"58.220.2.139:80","58.220.2.140:80",
"58.220.2.141:80","58.220.2.142:80",
"58.220.2.145:80","58.220.2.147:80",
"58.220.2.148:80","58.220.2.153:80"
};
//3个参数分别是域名后缀,线程数,IP数组
Ali ali = new Ali(".cn",4,ip);
ali.domainGenerator();
}


ok,到此大功告成。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: