爬虫实现:根据IP地址反查域名

4次阅读

共计 3871 个字符,预计需要花费 10 分钟才能阅读完成。

域名解析与 IP 地址
域名解析是把域名指向网站空间 IP,让人们通过注册的域名可以方便地访问到网站的一种服务;IP 地址是网络上标识站点的数字地址,为了方便记忆,采用域名来代替 IP 地址标识站点地址。域名解析就是域名到 IP 地址的转换过程,该过程由 DNS 服务器完成(来自百度百科)
先来了解两个知识点
1、一个域名同一时刻只能对应一个 IP 地址
2、一个 IP 地址可以解析绑定多个域名,没有限制
基于以上知识点,假如我们已知一个 IP 地址,我们怎么才能获取解析到该 IP 地址的所有域名信息呢?一种方式是国家工信部能开放查询接口以供查询(不知道会不会开放?);另外一种方式就是接下来我要分享的——爬虫实现:根据 IP 地址反查域名。
实现原理
实现原理其实很简单,现在已有网站提供了根据 IP 地址查询域名的功能,但是需要人为登录网站输入 IP 地址查询,我想要实现程序自动化查询,所以就想到了爬虫的方式,简单来说,就是模拟人的查询行为,将查询结果解析成我想要的域名列表。
以 site.ip138.com 为例,打开 F12,输入一个 IP 查询,观察控制台请求,看到下图中信息
请求地址为:http://site.ip138.com/119.75….
请求方式为:GET

然后,分析 Response,可以看到,在页面上看到的绑定域名信息就是下图红框中 <span> 的内容,所以只要能将 Response 的内容解析出来,获取到 <span> 的内容就可以得到想要的域名列表。

上述 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 上,欢迎下载学习

Gitee
Github

正文完
 0