1. 程式人生 > >多執行緒批量檢測未註冊域名

多執行緒批量檢測未註冊域名

最近想註冊一個域名,使用萬網嘗試了很多域名,基本都已被註冊。之前聽說雙拼域名很火,所以想寫個指令碼,看看哪些雙拼域名還未被註冊。

 

一、查詢介面

網上搜索了一下,萬網的域名查詢介面比較簡單易用,查詢URL格式為: http://panda.www.net.cn/cgi-bin/check.cgi?area_domain=aaa.com

返回值及含義:

210 : Domain name is available
211 : Domain name is not available
212 : Domain name is invalid
214 : Unknown error

 

二、程式設計思路

1. DomainGenerator讀取檔案pinyin.txt,獲取所有可用的拼音字母。遍歷拼音字母, 組裝成雙拼域名。這個拼音列表是從網上搜索來的,可能會有紕漏。

2. 建立域名檢測執行緒DomainRunner,每個執行緒採用httpclient呼叫萬網的域名查詢介面。

3. 每個執行緒呼叫DomainValidator檢查返回結果。

4. 執行緒ResultRunner將可用域名寫入domain.txt檔案。

 

三、核心程式碼

DomainGenerator.java, 啟動類,讀取拼音列表,組裝需要檢測的域名,建立檢測執行緒和結果處理執行緒。

 


    
  1. package com.learnworld;
  2. import java.util.List;
  3. import
    java.io.BufferedReader;
  4. import java.io.BufferedWriter;
  5. import java.io.FileReader;
  6. import java.io.FileWriter;
  7. import java.util.ArrayList;
  8. import java.util.concurrent.ArrayBlockingQueue;
  9. import java.util.concurrent.CountDownLatch;
  10. import java.util.concurrent.ExecutorService;
  11. import java.util.concurrent.Executors;
  12. import java.util.concurrent.LinkedBlockingQueue;
  13. import java.util.concurrent.atomic.AtomicInteger;
  14. import org.apache.http.impl.client.CloseableHttpClient;
  15. import org.apache.http.impl.client.HttpClients;
  16. import org.apache.http.impl.conn.PoolingHttpClientConnectionManager;
  17. public class DomainGenerator {
  18. public static void main(String[] args){
  19. // pinyin list, read from pinyin.txt
  20. List<String> items = new ArrayList<String>();
  21. // domain list, which need to check
  22. ArrayBlockingQueue<String> taskQueue = new ArrayBlockingQueue<String>( 163620);
  23. // available domain list, which need to save into file
  24. LinkedBlockingQueue<String> resultQueue = new LinkedBlockingQueue<String>();
  25. // counter, need to count unavailable domain statistical information
  26. AtomicInteger count = new AtomicInteger( 0);
  27. // Httpclient initialization
  28. PoolingHttpClientConnectionManager cm = new PoolingHttpClientConnectionManager();
  29. cm.setMaxTotal( 20);
  30. cm.setDefaultMaxPerRoute( 20);
  31. CloseableHttpClient httpClient = HttpClients.custom().setConnectionManager(cm).build();
  32. try {
  33. // pinyin.txt, used to save all available pinyin
  34. BufferedReader reader = new BufferedReader( new FileReader( "pinyin.txt"));
  35. // domain.txt, used to save all available domain result
  36. BufferedWriter writer = new BufferedWriter( new FileWriter( "domain.txt"));
  37. String item = null;
  38. while((item = reader.readLine()) != null){
  39. items.add(item);
  40. }
  41. // generate domain list
  42. for (String item1 : items){
  43. for (String item2 : items) {
  44. taskQueue.offer(item1 + item2 + ".com");
  45. }
  46. }
  47. int domainThreadNum = 3;
  48. CountDownLatch downLatch = new CountDownLatch(domainThreadNum);
  49. ExecutorService executor = Executors.newFixedThreadPool(domainThreadNum + 1);
  50. // start domain check thread
  51. for( int i = 0; i < domainThreadNum; i++){
  52. executor.execute( new DomainRunner(taskQueue, resultQueue, downLatch, count, httpClient));
  53. }
  54. // start result handle thread
  55. executor.execute( new ResultRunner(resultQueue, writer));
  56. downLatch.await();
  57. System.out.println( "All tasks are done!");
  58. // TODO, suggest use volatile flag to control ResultRunner
  59. executor.shutdownNow();
  60. reader.close();
  61. writer.close();
  62. httpClient.close();
  63. } catch (Exception e) {
  64. e.printStackTrace();
  65. }
  66. }
  67. }

 DomainRunner:域名檢測執行緒,從域名domainQueue中讀取域名,呼叫介面進行檢測。 如果域名可用,將結果放入resultQueue中等待寫入檔案。


    
  1. package com.learnworld;
  2. import java.io.IOException;
  3. import java.util.Calendar;
  4. import java.util.concurrent.ArrayBlockingQueue;
  5. import java.util.concurrent.CountDownLatch;
  6. import java.util.concurrent.LinkedBlockingQueue;
  7. import java.util.concurrent.atomic.AtomicInteger;
  8. import org.apache.http.HttpEntity;
  9. import org.apache.http.client.config.RequestConfig;
  10. import org.apache.http.client.methods.CloseableHttpResponse;
  11. import org.apache.http.client.methods.HttpGet;
  12. import org.apache.http.impl.client.CloseableHttpClient;
  13. import org.apache.http.protocol.BasicHttpContext;
  14. import org.apache.http.protocol.HttpContext;
  15. import org.apache.http.util.EntityUtils;
  16. public class DomainRunner implements Runnable {
  17. private ArrayBlockingQueue<String> domainQueue;
  18. private LinkedBlockingQueue<String> resultQueue;
  19. private CountDownLatch downLatch;
  20. private AtomicInteger count;
  21. private CloseableHttpClient httpClient;
  22. public DomainRunner(ArrayBlockingQueue<String> domainQueue,
  23. LinkedBlockingQueue<String> resultQueue, CountDownLatch downLatch,
  24. AtomicInteger count, CloseableHttpClient httpClient) {
  25. super();
  26. this.domainQueue = domainQueue;
  27. this.resultQueue = resultQueue;
  28. this.downLatch = downLatch;
  29. this.count = count;
  30. this.httpClient = httpClient;
  31. }
  32. @Override
  33. public void run() {
  34. String domain = null;
  35. while ((domain = domainQueue.poll()) != null) {
  36. boolean isDomainAvailable = false;
  37. RequestConfig requestConfig = RequestConfig.custom()
  38. .setSocketTimeout( 5000)
  39. .setConnectTimeout( 5000)
  40. .setConnectionRequestTimeout( 5000)
  41. .build();
  42. HttpGet httpGet = new HttpGet( "http://panda.www.net.cn/cgi-bin/check.cgi?area_domain=" + domain);
  43. httpGet.setConfig(requestConfig);
  44. httpGet.setHeader( "Connection", "close");
  45. HttpContext context = new BasicHttpContext();
  46. CloseableHttpResponse response = null;
  47. try {
  48. response = httpClient.execute(httpGet, context);
  49. HttpEntity entity = response.getEntity();
  50. int status = response.getStatusLine().getStatusCode();
  51. if (status >= 200 && status < 300) {
  52. String resultXml = EntityUtils.toString(entity);
  53. isDomainAvailable = DomainValidator.isAvailableDomainForResponse(resultXml);
  54. EntityUtils.consumeQuietly(entity);
  55. } else {
  56. System.out.println(domain + " check error.");
  57. }
  58. } catch (Exception e) {
  59. e.printStackTrace();
  60. } finally {
  61. try {
  62. httpGet.releaseConnection();
  63. if (response != null) {
  64. response.close();
  65. }
  66. } catch (IOException e) {
  67. e.printStackTrace();
  68. }
  69. }
  70. // result handle
  71. if(isDomainAvailable) {
  72. resultQueue.offer(domain);
  73. } else {
  74. int totalInvalid = count.addAndGet( 1);
  75. if (totalInvalid % 100 == 0) {
  76. System.out.println(totalInvalid + " " + Calendar.getInstance().getTime());
  77. }
  78. }
  79. }
  80. downLatch.countDown();
  81. }
  82. }

 

DomainValidator: 對萬網返回結果進行檢查,判斷域名是否可用。


    
  1. package com.learnworld;
  2. public class DomainValidator {
  3. public static boolean isAvailableDomainForResponse(String responseXml){
  4. if(responseXml == null || responseXml.isEmpty()){
  5. return false;
  6. }
  7. if(responseXml.contains( "<original>210")){
  8. return true;
  9. } else if(responseXml.contains( "<original>211")
  10. || responseXml.contains( "<original>212")
  11. || responseXml.contains( "<original>214")){
  12. return false;
  13. } else {
  14. System.out.println( "api callback error!");
  15. try {
  16. Thread.sleep( 60000);
  17. } catch (InterruptedException e) {
  18. e.printStackTrace();
  19. }
  20. return false;
  21. }
  22. }
  23. }

 

ResultRunner: 結果處理執行緒,將可用域名寫入檔案domain.txt中。


    
  1. <