域名解析與IP地址
域名解析是把域名指向網站空間IP,讓人們通過註冊的域名可以方便地訪問到網站的一種服務;IP地址是網路上標識站點的數字地址,為了方便記憶,採用域名來代替IP地址標識站點地址。域名解析就是域名到IP地址的轉換過程,該過程由DNS伺服器完成(來自百度百科)
先來了解兩個知識點
1、一個域名同一時刻只能對應一個IP地址
2、一個IP地址可以解析繫結多個域名,沒有限制
基於以上知識點,假如我們已知一個IP地址,我們怎麼才能獲取解析到該IP地址的所有域名資訊呢?一種方式是國家工信部能開放查詢介面以供查詢(不知道會不會開放?);另外一種方式就是接下來我要分享的——爬蟲實現:根據IP地址反查域名。
實現原理
實現原理其實很簡單,現在已有網站提供了根據IP地址查詢域名的功能,但是需要人為登入網站輸入IP地址查詢,我想要實現程式自動化查詢,所以就想到了爬蟲的方式,簡單來說,就是模擬人的查詢行為,將查詢結果解析成我想要的域名列表。
以site.ip138.com
為例,開啟F12
,輸入一個IP查詢,觀察控制檯請求,看到下圖中資訊
請求地址為:site.ip138.com/119.75.217.…
請求方式為:GET
然後,分析Response,可以看到,在頁面上看到的繫結域名資訊就是下圖紅框中的內容,所以只要能將Response的內容解析出來,獲取到的內容就可以得到想要的域名列表。
上述Response是HTML頁面,使用jsoup
來解析HTML簡直完美。
jsoup是什麼?
jsoup 是一款Java 的HTML解析器,可直接解析某個URL地址、HTML文字內容。它提供了一套非常省力的API,可通過DOM,CSS以及類似於jQuery的操作方法來取出和運算元據。
//解析成Document物件
Document document = Jsoup.parse(result);
if (document == null) {
logger.error("Jsoup parse get document null!");
}
//根據ID屬性“list”獲取元素Element物件(有沒有感覺很像jQuery?)
Element listEle = document.getElementById("list");
//根據class屬性和屬性值篩選元素Element集合,並通過eachText()遍歷元素內容
return listEle.getElementsByAttributeValue("target", "_blank").eachText();
複製程式碼
result的內容通過HttpClient模擬HTTP請求
HttpGet httpGet = new HttpGet(url);
httpGet.setHeader("Accept", "text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8");
httpGet.setHeader("Accept-Encoding", "gzip, deflate");
httpGet.setHeader("Accept-Language", "zh-CN,zh;q=0.9");
httpGet.setHeader("Cache-Control", "max-age=0");
httpGet.setHeader("Connection", "keep-alive");
httpGet.setHeader("Cookie", "Hm_lvt_d39191a0b09bb1eb023933edaa468cd5=1553090128; BAIDU_SSP_lcr=https://www.baidu.com/link?url=FS0ccst469D77DpdXpcGyJhf7OSTLTyk6VcMEHxT_9_&wd=&eqid=fa0e26f70002e7dd000000065c924649; pgv_pvi=6200530944; pgv_si=s4712839168; Hm_lpvt_d39191a0b09bb1eb023933edaa468cd5=1553093270");
httpGet.setHeader("DNT", "1");
httpGet.setHeader("Host", host);
httpGet.setHeader("Upgrade-Insecure-Requests", "1");
httpGet.setHeader("User-Agent", "Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/63.0.3239.132 Safari/537.36");
String result = HttpUtils.doGet(httpGet);
複製程式碼
HTTP請求工具類
public class HttpUtils {
private static Logger logger = LoggerFactory.getLogger(HttpUtils.class);
public static String doGet(HttpGet httpGet) {
CloseableHttpClient httpClient = null;
try {
httpClient = HttpClients.createDefault();
RequestConfig requestConfig = RequestConfig.custom()
.setConnectTimeout(5000).setConnectionRequestTimeout(10000)
.setSocketTimeout(5000).build();
httpGet.setConfig(requestConfig);
HttpResponse httpResponse = httpClient.execute(httpGet);
if (httpResponse.getStatusLine().getStatusCode() == 200 ||
httpResponse.getStatusLine().getStatusCode() == 302) {
HttpEntity entity = httpResponse.getEntity();
return EntityUtils.toString(entity, "utf-8");
} else {
logger.error("Request StatusCode={}", httpResponse.getStatusLine().getStatusCode());
}
} catch (Exception e) {
logger.error("Request Exception={}:", e);
} finally {
if (httpClient != null) {
try {
httpClient.close();
} catch (IOException e) {
logger.error("關閉httpClient失敗", e);
}
}
}
return null;
}
}
複製程式碼
新增Controller
@RestController
public class DomainSpiderController {
private static Logger logger = LoggerFactory.getLogger(DomainSpiderController.class);
@Autowired
private DomainSpiderService domainSpiderService;
/**
* @param ip 119.75.217.109
* @return
*/
@RequestMapping("/spider/{ip}")
@ResponseBody
public List<String> domainSpider(@PathVariable("ip") String ip) {
long startTime = System.currentTimeMillis();
List<String> domains = domainSpiderService.domainSpiderOfIp138(ip);
if(domains == null || domains.size() == 0) {
domains = domainSpiderService.domainSpiderOfAizan(ip);
}
long endTime = System.currentTimeMillis();
logger.info("完成爬蟲任務總耗時:{}s", (endTime - startTime) / 1000);
return domains;
}
}
複製程式碼
啟動Spring Boot應用,訪問瀏覽器:http://localhost:8080/spider/119.75.217.109 獲得返回結果如下:
怎麼樣?是不是很簡單?
優化改進:有時候僅僅通過一個網站查詢的域名資料可能不太準確,甚至查詢不到資料,我們也沒法判斷誰才是正確的,所以,可以通過爬取多個網站的結果結合起來使用,例如:dns.aizhan.com
提出疑問:這些提供根據IP反查域名的網站,是怎麼實現的呢?我諮詢過其他人,他們的回答是這些網站收集了很多IP和域名的對應關係,真實情況是這樣的嗎?
示例原始碼
- domain-spider
程式碼已上傳至碼雲
和Github
上,歡迎下載學習