基于2.0版本的基础改动了以下几个地方:
IP-网段过滤,可以快速把各种网段如:192.168.1、170.18、192.168.1.0/2轻松去掉,提高你的干活效率!!!
显示被过滤的IP网段
统一各个模块的滑动条样式
界面样式预览:

html
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>IP与域名提取工具 - 极速版</title>
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css">
<style>
* {
margin: 0;
padding: 0;
box-sizing: border-box;
font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
}
body {
background: linear-gradient(135deg, #1a2a6c, #b21f1f, #1a2a6c);
min-height: 100vh;
display: flex;
justify-content: center;
align-items: center;
padding: 20px;
color: #fff;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
}
.container {
width: 100%;
max-width: 1200px;
background: rgba(0, 0, 20, 0.8);
border-radius: 20px;
box-shadow: 0 15px 35px rgba(0, 0, 0, 0.5);
overflow: hidden;
backdrop-filter: blur(10px);
border: 1px solid rgba(255, 255, 255, 0.1);
}
header {
background: rgba(0, 10, 30, 0.9);
padding: 25px 40px;
text-align: center;
border-bottom: 2px solid #00ccff;
position: relative;
}
h1 {
font-size: 2.5rem;
margin-bottom: 10px;
background: linear-gradient(90deg, #00ccff, #00ffcc);
-webkit-background-clip: text;
background-clip: text;
color: transparent;
text-shadow: 0 0 15px rgba(0, 204, 255, 0.5);
}
.subtitle {
color: #a0d2ff;
font-size: 1.1rem;
opacity: 0.9;
max-width: 800px;
margin: 0 auto;
line-height: 1.6;
}
.features {
display: flex;
justify-content: center;
flex-wrap: wrap;
gap: 15px;
margin-top: 20px;
}
.feature {
background: rgba(0, 204, 255, 0.15);
border-radius: 8px;
padding: 8px 15px;
font-size: 0.9rem;
display: flex;
align-items: center;
gap: 8px;
color: #fff;
}
.mode-toggle {
position: absolute;
top: 20px;
right: 20px;
background: rgba(0, 204, 255, 0.2);
border-radius: 20px;
padding: 8px 16px;
display: flex;
align-items: center;
gap: 8px;
cursor: pointer;
transition: all 0.3s ease;
}
.mode-toggle:hover {
background: rgba(0, 204, 255, 0.3);
}
.mode-indicator {
width: 12px;
height: 12px;
border-radius: 50%;
background: #00ff00;
box-shadow: 0 0 8px #00ff00;
}
.mode-indicator.off {
background: #ff5555;
box-shadow: 0 0 8px #ff5555;
}
.tooltip {
position: absolute;
top: -40px;
right: 0;
background: rgba(0, 40, 80, 0.9);
color: #00ffcc;
padding: 8px 12px;
border-radius: 8px;
font-size: 0.8rem;
white-space: nowrap;
opacity: 0;
transition: opacity 0.3s ease;
pointer-events: none;
}
.mode-toggle:hover .tooltip {
opacity: 1;
}
.main-content {
display: flex;
flex-wrap: wrap;
padding: 30px;
gap: 30px;
}
.input-section {
flex: 1;
min-width: 300px;
}
.output-section {
flex: 1;
min-width: 300px;
display: flex;
flex-direction: column;
gap: 30px;
}
.section-title {
font-size: 1.4rem;
margin-bottom: 15px;
color: #00ccff;
display: flex;
align-items: center;
gap: 10px;
}
.section-title i {
font-size: 1.2rem;
}
textarea {
width: 100%;
height: 250px;
background: rgba(0, 20, 40, 0.7);
border: 1px solid rgba(0, 204, 255, 0.4);
border-radius: 12px;
padding: 20px;
color: #fff;
font-size: 1rem;
resize: none;
overflow-y: auto;
overflow-x: hidden;
transition: all 0.3s ease;
}
textarea::-webkit-scrollbar {
width: 8px;
}
textarea::-webkit-scrollbar-track {
background: rgba(0, 0, 0, 0.2);
border-radius: 4px;
}
textarea::-webkit-scrollbar-thumb {
background: rgba(0, 204, 255, 0.5);
border-radius: 4px;
}
textarea:focus {
outline: none;
border-color: #00ccff;
box-shadow: 0 0 15px rgba(0, 204, 255, 0.4);
}
textarea::placeholder {
color: rgba(160, 210, 255, 0.7);
}
/* 网段过滤输入框样式 */
#filterCidrText {
height: 120px;
margin-top: 15px;
}
.button-group {
display: flex;
gap: 15px;
margin-top: 20px;
flex-wrap: wrap;
}
.btn {
flex: 1;
min-width: 140px;
padding: 15px 20px;
border: none;
border-radius: 10px;
font-size: 1.1rem;
font-weight: 600;
cursor: pointer;
transition: all 0.3s ease;
display: flex;
align-items: center;
justify-content: center;
gap: 10px;
}
.btn-primary {
background: linear-gradient(90deg, #00a6ff, #00ffc3);
color: #00203d;
}
.btn-secondary {
background: rgba(255, 255, 255, 0.1);
color: #00ccff;
border: 1px solid rgba(0, 204, 255, 0.4);
}
.btn-orange {
background: rgba(255, 165, 0, 0.2);
color: #ffaa33;
border: 1px solid rgba(255, 165, 0, 0.4);
}
.btn:hover {
transform: translateY(-3px);
box-shadow: 0 7px 15px rgba(0, 0, 0, 0.3);
}
.btn:active {
transform: translateY(1px);
}
.btn-primary:hover {
background: linear-gradient(90deg, #0095e6, #00e6b8);
}
.btn-secondary:hover {
background: rgba(255, 255, 255, 0.15);
border-color: #00ccff;
}
.btn-orange:hover {
background: rgba(255, 165, 0, 0.3);
}
.results-box {
background: rgba(0, 20, 40, 0.7);
border: 1px solid rgba(0, 204, 255, 0.4);
border-radius: 12px;
padding: 20px;
min-height: 250px;
position: relative;
}
.box-header {
display: flex;
justify-content: space-between;
align-items: center;
margin-bottom: 15px;
gap: 15px;
flex-wrap: wrap;
}
.copy-btn {
background: rgba(0, 204, 255, 0.2);
color: #00ccff;
border: none;
padding: 8px 15px;
border-radius: 8px;
cursor: pointer;
transition: all 0.3s ease;
display: flex;
align-items: center;
gap: 8px;
flex-shrink: 0;
}
.copy-btn:hover {
background: rgba(0, 204, 255, 0.3);
}
.results-content {
max-height: 200px;
overflow-y: auto;
padding-right: 10px;
}
.results-content::-webkit-scrollbar {
width: 8px;
}
.results-content::-webkit-scrollbar-track {
background: rgba(0, 0, 0, 0.2);
border-radius: 4px;
}
.results-content::-webkit-scrollbar-thumb {
background: rgba(0, 204, 255, 0.5);
border-radius: 4px;
}
.result-item {
padding: 10px 15px;
background: rgba(0, 40, 80, 0.4);
border-radius: 8px;
margin-bottom: 10px;
display: flex;
justify-content: space-between;
align-items: center;
animation: fadeIn 0.5s ease;
color: #fff;
font-weight: 500;
letter-spacing: 0.03em;
}
.result-item.duplicate {
background: rgba(180, 60, 60, 0.4);
color: #ffaaaa;
text-decoration: line-through;
}
@keyframes fadeIn {
from { opacity: 0; transform: translateY(10px); }
to { opacity: 1; transform: translateY(0); }
}
.result-item .copy-icon {
color: #00ccff;
cursor: pointer;
font-size: 1.1rem;
transition: all 0.2s ease;
}
.result-item .copy-icon:hover {
color: #00ffcc;
transform: scale(1.1);
}
.empty-message {
color: #a0d2ff;
text-align: center;
padding: 20px;
font-style: italic;
text-shadow: 0 1px 2px rgba(0,0,0,0.5);
}
.counter {
background: rgba(0, 204, 255, 0.2);
border-radius: 20px;
padding: 3px 10px;
font-size: 0.9rem;
}
.counter.warning {
background: rgba(255, 204, 0, 0.2);
}
.notification {
position: fixed;
top: 20px;
right: 20px;
background: rgba(0, 40, 80, 0.9);
color: #00ffcc;
padding: 15px 25px;
border-radius: 10px;
box-shadow: 0 5px 15px rgba(0, 0, 0, 0.3);
display: flex;
align-items: center;
gap: 10px;
transform: translateX(120%);
transition: transform 0.4s ease;
z-index: 1000;
border: 1px solid rgba(0, 204, 255, 0.4);
}
.notification.warning {
background: rgba(100, 60, 0, 0.9);
color: #ffcc00;
border-color: rgba(255, 204, 0, 0.4);
}
.notification.show {
transform: translateX(0);
}
.filter-info {
background: rgba(0, 40, 80, 0.5);
border-radius: 8px;
padding: 12px;
margin-top: 15px;
font-size: 0.9rem;
border-left: 3px solid #00ccff;
display: flex;
align-items: center;
gap: 10px;
color: #fff;
}
.unique-info {
background: rgba(255, 204, 0, 0.15);
border-left-color: #ffcc00;
}
/* 被过滤的IP网段模块样式(和重复IP模块保持一致) */
.filtered-by-cidr-container {
background: rgba(150, 50, 50, 0.3);
border: 1px solid rgba(255, 100, 100, 0.4);
border-radius: 12px;
margin-top: 20px;
overflow: hidden;
max-height: 0;
transition: max-height 0.4s ease;
}
.filtered-by-cidr-container.show {
max-height: 300px;
}
.filtered-by-cidr-header {
padding: 10px 15px;
display: flex;
justify-content: space-between;
align-items: center;
cursor: pointer;
background: rgba(180, 60, 60, 0.4);
color: #fff;
}
.filtered-by-cidr-content {
max-height: 200px;
overflow-y: auto;
padding: 10px;
}
.filtered-by-cidr-item {
padding: 8px 15px;
background: rgba(180, 60, 60, 0.3);
border-radius: 8px;
margin-bottom: 8px;
display: flex;
justify-content: space-between;
align-items: center;
color: #fff;
}
.filtered-count {
background: rgba(255, 100, 100, 0.5);
border-radius: 12px;
padding: 2px 8px;
font-size: 0.8rem;
}
/* 重复IP列表样式 */
.duplicate-ips-container {
background: rgba(150, 50, 50, 0.3);
border: 1px solid rgba(255, 100, 100, 0.4);
border-radius: 12px;
margin-top: 20px;
overflow: hidden;
max-height: 0;
transition: max-height 0.4s ease;
}
.duplicate-ips-container.show {
max-height: 500px;
}
.duplicate-ips-header {
padding: 10px 15px;
display: flex;
justify-content: space-between;
align-items: center;
cursor: pointer;
background: rgba(180, 60, 60, 0.4);
color: #fff;
}
.duplicate-ips-content {
max-height: 200px;
overflow-y: auto;
padding: 10px;
}
/* 被过滤模块滚动条:与"IP地址"结果区域保持一致 */
.filtered-by-cidr-content::-webkit-scrollbar,
.duplicate-ips-content::-webkit-scrollbar {
width: 8px;
}
.filtered-by-cidr-content::-webkit-scrollbar-track,
.duplicate-ips-content::-webkit-scrollbar-track {
background: rgba(0, 0, 0, 0.2);
border-radius: 4px;
}
.filtered-by-cidr-content::-webkit-scrollbar-thumb,
.duplicate-ips-content::-webkit-scrollbar-thumb {
background: rgba(0, 204, 255, 0.5);
border-radius: 4px;
}
.duplicate-ip-item {
padding: 8px 15px;
background: rgba(180, 60, 60, 0.3);
border-radius: 8px;
margin-bottom: 8px;
display: flex;
justify-content: space-between;
align-items: center;
color: #fff;
}
.duplicate-count {
background: rgba(255, 100, 100, 0.5);
border-radius: 12px;
padding: 2px 8px;
font-size: 0.8rem;
}
/* 按钮分组间距 */
.action-buttons {
display: flex;
gap: 15px;
flex-wrap: wrap;
}
/* 结果框标题区 */
.results-header-container {
display: flex;
justify-content: space-between;
align-items: center;
width: 100%;
flex-wrap: wrap;
gap: 15px;
}
/* 顶部控制区间距 */
.top-controls {
display: flex;
flex-wrap: wrap;
justify-content: space-between;
align-items: center;
gap: 15px;
width: 100%;
}
@media (max-width: 768px) {
.main-content {
flex-direction: column;
}
h1 {
font-size: 2rem;
}
.features {
flex-direction: column;
align-items: center;
}
.mode-toggle {
position: static;
margin-top: 15px;
align-self: center;
}
.box-header {
flex-direction: column;
align-items: flex-start;
}
.action-buttons {
width: 100%;
justify-content: space-between;
margin-top: 10px;
}
.copy-btn {
width: 100%;
margin-top: 10px;
}
}
</style>
</head>
<body>
<div class="container">
<header>
<h1><i class="fas fa-network-wired"></i> IP与域名提取工具</h1>
<p class="subtitle">从文本中智能提取IP地址和域名,提供多种过滤模式与重复IP查看功能</p>
<div class="mode-toggle" id="modeToggle">
<div class="tooltip">切换IP去重模式(唯一IP/传统去重)</div>
<div class="mode-indicator" id="modeIndicator"></div>
<span>唯一IP模式</span>
</div>
<div class="features">
<div class="feature"><i class="fas fa-check-circle"></i> 智能域名识别</div>
<div class="feature"><i class="fas fa-filter"></i> IP过滤选项</div>
<div class="feature"><i class="fas fa-eye"></i> 查看重复IP</div>
<div class="feature"><i class="fas fa-copy"></i> 一键复制</div>
</div>
</header>
<div class="main-content">
<div class="input-section">
<h2 class="section-title"><i class="fas fa-paste"></i> 粘贴文本内容</h2>
<textarea id="inputText" placeholder="在此处粘贴包含IP地址和域名的文本...">访问我们的网站:www.example.com 或 example.org
服务器IP:192.168.1.1 和 10.0.0.1
测试域名:sub.domain.co.uk, another.test.com
重复IP:42.236.17.33 和 42.236.17.33
其他IP:111.225.149.56, 182.98.61.12, 38.207.178.220
测试误识别情况:
文件:202408.rar (不应被识别为域名)
文件:report2024.pdf (不应被识别)
合法域名:123domain.com (应该被识别)
更多重复测试:
192.168.1.1 再次出现
10.0.0.1 和 10.0.0.1 是重复的
42.236.17.33 第三次出现</textarea>
<!-- 新增:IP网段过滤输入框 -->
<h2 class="section-title" style="margin-top:20px;"><i class="fas fa-shield-alt"></i> 过滤IP网段(CIDR)</h2>
<textarea id="filterCidrText" placeholder="每行一个规则,例如:
1.71.146.0/23
14.116.245.0/24
192.168.
192.168.1
"></textarea>
<!-- 新增:被过滤的IP网段模块 -->
<div id="filteredByCidrContainer" class="filtered-by-cidr-container">
<div class="filtered-by-cidr-header">
<span><i class="fas fa-ban"></i> 被过滤的IP网段</span>
<span id="filteredByCidrCount" class="filtered-count">0个IP被过滤</span>
</div>
<div id="filteredByCidrContent" class="filtered-by-cidr-content">
<div class="empty-message">暂无IP被网段过滤</div>
</div>
</div>
<div class="button-group">
<button id="extractBtn" class="btn btn-primary">
<i class="fas fa-magic"></i> 提取IP和域名
</button>
<button id="clearBtn" class="btn btn-secondary">
<i class="fas fa-trash-alt"></i> 清除内容
</button>
</div>
</div>
<div class="output-section">
<div class="ip-results">
<div class="box-header">
<div class="results-header-container">
<h2 class="section-title"><i class="fas fa-globe"></i> IP地址 <span id="ipCount" class="counter">0</span></h2>
<div class="action-buttons">
<button id="showDuplicatesBtn" class="copy-btn btn-orange">
<i class="fas fa-eye"></i> 显示重复IP
</button>
<button id="copyIpBtn" class="copy-btn">
<i class="fas fa-copy"></i> 复制所有
</button>
</div>
</div>
</div>
<div class="results-box">
<div id="ipResults" class="results-content">
<div class="empty-message">提取的IP地址将显示在这里<br><small>重复IP将被完全移除</small></div>
</div>
</div>
<!-- 重复IP列表容器 -->
<div id="duplicateIpsContainer" class="duplicate-ips-container">
<div class="duplicate-ips-header">
<span><i class="fas fa-exclamation-circle"></i> 被过滤的重复IP地址</span>
<span id="duplicateCount" class="duplicate-count">0个重复</span>
</div>
<div id="duplicateIpsContent" class="duplicate-ips-content">
<div class="empty-message">没有重复IP地址</div>
</div>
</div>
</div>
<div class="domain-results">
<div class="box-header">
<div class="top-controls">
<h2 class="section-title"><i class="fas fa-server"></i> 域名 <span id="domainCount" class="counter">0</span></h2>
<button id="copyDomainBtn" class="copy-btn">
<i class="fas fa-copy"></i> 复制所有域名
</button>
</div>
</div>
<div class="results-box">
<div id="domainResults" class="results-content">
<div class="empty-message">提取的域名将显示在这里<br><small>保留唯一的域名</small></div>
</div>
</div>
</div>
</div>
</div>
</div>
<div id="notification" class="notification">
<i class="fas fa-check-circle"></i>
<span id="notificationText">已复制到剪贴板!</span>
</div>
<script>
document.addEventListener('DOMContentLoaded', function() {
// DOM元素
const inputText = document.getElementById('inputText');
const filterCidrText = document.getElementById('filterCidrText');
const extractBtn = document.getElementById('extractBtn');
const clearBtn = document.getElementById('clearBtn');
const ipResults = document.getElementById('ipResults');
const domainResults = document.getElementById('domainResults');
const copyIpBtn = document.getElementById('copyIpBtn');
const copyDomainBtn = document.getElementById('copyDomainBtn');
const ipCount = document.getElementById('ipCount');
const domainCount = document.getElementById('domainCount');
const notification = document.getElementById('notification');
const notificationText = document.getElementById('notificationText');
const modeToggle = document.getElementById('modeToggle');
const modeIndicator = document.getElementById('modeIndicator');
const showDuplicatesBtn = document.getElementById('showDuplicatesBtn');
const duplicateIpsContainer = document.getElementById('duplicateIpsContainer');
const duplicateIpsContent = document.getElementById('duplicateIpsContent');
const duplicateCount = document.getElementById('duplicateCount');
// 新增:被过滤的IP网段模块DOM
const filteredByCidrContainer = document.getElementById('filteredByCidrContainer');
const filteredByCidrContent = document.getElementById('filteredByCidrContent');
const filteredByCidrCount = document.getElementById('filteredByCidrCount');
let uniqueMode = true; // 默认开启唯一IP模式
let duplicatesMap = new Map(); // 存储重复IP及其出现次数
let showDuplicates = false; // 是否显示重复IP列表
let filteredByCidrList = []; // 存储被网段过滤的IP
// ---------------- IP规则过滤核心函数(支持 CIDR + IP前缀) ----------------
function isValidIPv4(ip) {
const parts = ip.split('.');
return parts.length === 4 && parts.every(part => {
if (!/^\d{1,3}$/.test(part)) return false;
const num = parseInt(part, 10);
return num >= 0 && num <= 255;
});
}
function ipToInt(ip) {
return ip.split('.').reduce((a, b) => (a << 8) | parseInt(b, 10), 0) >>> 0;
}
function parseIpFilterRule(ruleText) {
const rule = ruleText.trim().replace(/\s+/g, '');
if (!rule) return null;
// 1) CIDR规则:例如 1.71.146.0/23
if (rule.includes('/')) {
const [ipStr, prefixStr] = rule.split('/');
const prefix = parseInt(prefixStr, 10);
if (
rule.split('/').length === 2 &&
isValidIPv4(ipStr) &&
/^\d{1,2}$/.test(prefixStr) &&
prefix >= 0 &&
prefix <= 32
) {
return { type: 'cidr', value: rule };
}
return null;
}
// 2) 完整IP规则:例如 192.168.1.10,仅过滤这个IP
if (isValidIPv4(rule)) {
return { type: 'exact', value: rule };
}
// 3) IP前缀规则:例如 192.168. / 192.168.1 / 172.2.18.
// 192.168.1 会按 192.168.1.* 处理,不会误伤 192.168.10.*
const normalized = rule.endsWith('.') ? rule.slice(0, -1) : rule;
const parts = normalized.split('.');
if (
parts.length >= 1 &&
parts.length <= 3 &&
parts.every(part => /^\d{1,3}$/.test(part) && parseInt(part, 10) >= 0 && parseInt(part, 10) <= 255)
) {
return { type: 'prefix', value: normalized + '.' };
}
return null;
}
function cidrToRange(cidr) {
const [ipStr, prefixStr] = cidr.split('/');
const prefix = parseInt(prefixStr, 10);
const ipInt = ipToInt(ipStr);
const mask = prefix === 0 ? 0 : (0xFFFFFFFF << (32 - prefix)) >>> 0;
const start = ipInt & mask;
const end = start | (~mask >>> 0);
return { start, end };
}
function isIpMatchedFilterRules(ip, filterRules) {
const ipInt = ipToInt(ip);
for (const rule of filterRules) {
try {
if (rule.type === 'cidr') {
const { start, end } = cidrToRange(rule.value);
if (ipInt >= start && ipInt <= end) return true;
} else if (rule.type === 'exact') {
if (ip === rule.value) return true;
} else if (rule.type === 'prefix') {
if (ip.startsWith(rule.value)) return true;
}
} catch (e) {}
}
return false;
}
// -----------------------------------------------------------
// 切换IP处理模式
modeToggle.addEventListener('click', function() {
uniqueMode = !uniqueMode;
if (uniqueMode) {
modeIndicator.classList.remove('off');
modeToggle.querySelector('span').textContent = '唯一IP模式';
showNotification('唯一IP模式:完全移除重复IP', false);
} else {
modeIndicator.classList.add('off');
modeToggle.querySelector('span').textContent = '传统去重模式';
showNotification('传统去重模式:重复IP保留一个实例', true);
}
// 隐藏重复IP列表
showDuplicates = false;
duplicateIpsContainer.classList.remove('show');
showDuplicatesBtn.innerHTML = '<i class="fas fa-eye"></i> 显示重复IP';
// 如果有文本内容,重新运行提取
if (inputText.value.trim()) {
extractBtn.click();
}
});
// 切换显示重复IP列表
showDuplicatesBtn.addEventListener('click', function() {
showDuplicates = !showDuplicates;
if (showDuplicates) {
duplicateIpsContainer.classList.add('show');
this.innerHTML = '<i class="fas fa-eye-slash"></i> 隐藏重复IP';
} else {
duplicateIpsContainer.classList.remove('show');
this.innerHTML = '<i class="fas fa-eye"></i> 显示重复IP';
}
});
// 提取IP和域名
extractBtn.addEventListener('click', function() {
const text = inputText.value;
const filterRules = filterCidrText.value
.split('\n')
.map(parseIpFilterRule)
.filter(Boolean);
if (!text.trim()) {
showNotification('请先输入文本内容', true);
return;
}
// 提取IP地址 (IPv4格式)
const ipRegex = /\b(?:\d{1,3}\.){3}\d{1,3}\b/g;
const ipMatches = text.match(ipRegex) || [];
// 第一步:过滤掉在黑名单网段内的IP,并记录被过滤的IP
filteredByCidrList = [];
const filteredByCidr = ipMatches.filter(ip => {
if (isIpMatchedFilterRules(ip, filterRules)) {
filteredByCidrList.push(ip);
return false;
}
return true;
});
// 更新被网段过滤的IP列表
updateFilteredByCidrList();
// 重置重复IP映射
duplicatesMap = new Map();
// 按模式处理IP
let uniqueIPs;
if (uniqueMode) {
// 唯一IP模式:完全移除重复IP
const ipCountMap = new Map();
// 计数每个IP出现的次数
filteredByCidr.forEach(ip => {
ipCountMap.set(ip, (ipCountMap.get(ip) || 0) + 1);
});
// 只保留出现一次的唯一IP
uniqueIPs = filteredByCidr.filter(ip => ipCountMap.get(ip) === 1);
// 收集重复IP及其出现次数
ipCountMap.forEach((count, ip) => {
if (count > 1) {
duplicatesMap.set(ip, count);
}
});
} else {
// 传统模式:去重保留唯一IP
uniqueIPs = [...new Set(filteredByCidr)];
// 在传统模式下也收集重复IP信息用于显示
const ipCountMap = new Map();
filteredByCidr.forEach(ip => {
ipCountMap.set(ip, (ipCountMap.get(ip) || 0) + 1);
});
ipCountMap.forEach((count, ip) => {
if (count > 1) {
duplicatesMap.set(ip, count);
}
});
}
// 更新重复IP列表
updateDuplicateIPsList();
// 增强版域名提取 - 避免误识别文件名
const domainRegex = /\b(?:[a-z][a-z0-9-]*\.)+[a-z]{2,}\b/gi;
const rawDomains = text.match(domainRegex) || [];
const domains = [...new Set(rawDomains.filter(domain => {
const parts = domain.split('.');
const mainPart = parts.slice(0, -1).join('');
return !/^\d+$/.test(mainPart);
}))];
// 显示结果
displayResults(uniqueIPs, ipResults, ipCount, 'ip', filteredByCidr);
displayResults(domains, domainResults, domainCount, 'domain');
});
// 更新被网段过滤的IP列表
function updateFilteredByCidrList() {
filteredByCidrContent.innerHTML = '';
if (filteredByCidrList.length === 0) {
filteredByCidrContent.innerHTML = '<div class="empty-message">暂无IP被网段过滤</div>';
filteredByCidrCount.textContent = '0个IP被过滤';
filteredByCidrContainer.classList.remove('show');
return;
}
// 去重并统计出现次数
const filteredCountMap = new Map();
filteredByCidrList.forEach(ip => {
filteredCountMap.set(ip, (filteredCountMap.get(ip) || 0) + 1);
});
filteredByCidrCount.textContent = `${filteredCountMap.size}个IP被过滤`;
filteredByCidrContainer.classList.add('show');
const sortedFiltered = [...filteredCountMap.entries()]
.sort((a, b) => b[1] - a[1]);
sortedFiltered.forEach(([ip, count]) => {
const filteredItem = document.createElement('div');
filteredItem.className = 'filtered-by-cidr-item';
filteredItem.innerHTML = `
<span>${ip}</span>
<div class="filtered-count">出现 ${count} 次</div>
`;
filteredByCidrContent.appendChild(filteredItem);
});
}
// 更新重复IP列表
function updateDuplicateIPsList() {
duplicateIpsContent.innerHTML = '';
if (duplicatesMap.size === 0) {
duplicateIpsContent.innerHTML = '<div class="empty-message">没有重复IP地址</div>';
duplicateCount.textContent = '0个重复';
return;
}
duplicateCount.textContent = `${duplicatesMap.size}个重复`;
const sortedDuplicates = [...duplicatesMap.entries()]
.sort((a, b) => b[1] - a[1]);
sortedDuplicates.forEach(([ip, count]) => {
const duplicateItem = document.createElement('div');
duplicateItem.className = 'duplicate-ip-item';
duplicateItem.innerHTML = `
<span>${ip}</span>
<div class="duplicate-count">出现 ${count} 次</div>
`;
duplicateIpsContent.appendChild(duplicateItem);
});
}
// 显示结果函数
function displayResults(items, container, counter, type, originalItems = []) {
container.innerHTML = '';
if (items.length === 0) {
container.innerHTML = `<div class="empty-message">未找到${type === 'ip' ? 'IP地址' : '域名'}</div>`;
counter.textContent = '0';
counter.className = 'counter';
return;
}
counter.textContent = items.length;
if (type === 'ip' && uniqueMode && originalItems.length > items.length) {
counter.className = 'counter warning';
} else {
counter.className = 'counter';
}
items.forEach(item => {
const resultItem = document.createElement('div');
resultItem.className = 'result-item';
const isDuplicate = type === 'ip' && !uniqueMode &&
originalItems.filter(ip => ip === item).length > 1;
if (isDuplicate) {
resultItem.classList.add('duplicate');
}
resultItem.innerHTML = `
<span>${item}</span>
<i class="fas fa-copy copy-icon" data-value="${item}"></i>
`;
container.appendChild(resultItem);
});
container.querySelectorAll('.copy-icon').forEach(icon => {
icon.addEventListener('click', function() {
const value = this.getAttribute('data-value');
copyToClipboard(value, '已复制: ' + value);
});
});
}
// 复制IP地址
copyIpBtn.addEventListener('click', function() {
const ips = Array.from(ipResults.querySelectorAll('.result-item span'))
.map(span => span.textContent)
.join('\n');
if (ips) {
copyToClipboard(ips, '已复制所有IP地址');
} else {
showNotification('没有可复制的IP地址', true);
}
});
// 复制域名
copyDomainBtn.addEventListener('click', function() {
const domains = Array.from(domainResults.querySelectorAll('.result-item span'))
.map(span => span.textContent)
.join('\n');
if (domains) {
copyToClipboard(domains, '已复制所有域名');
} else {
showNotification('没有可复制的域名', true);
}
});
// 清除内容
clearBtn.addEventListener('click', function() {
inputText.value = '';
filterCidrText.value = '';
ipResults.innerHTML = '<div class="empty-message">提取的IP地址将显示在这里<br><small>重复IP将被完全移除</small></div>';
domainResults.innerHTML = '<div class="empty-message">提取的域名将显示在这里<br><small>保留唯一的域名</small></div>';
ipCount.textContent = '0';
domainCount.textContent = '0';
ipCount.className = 'counter';
domainCount.className = 'counter';
duplicatesMap = new Map();
filteredByCidrList = [];
updateDuplicateIPsList();
updateFilteredByCidrList();
showDuplicates = false;
duplicateIpsContainer.classList.remove('show');
showDuplicatesBtn.innerHTML = '<i class="fas fa-eye"></i> 显示重复IP';
});
// 复制到剪贴板函数
function copyToClipboard(text, message) {
navigator.clipboard.writeText(text).then(() => {
showNotification(message, false);
}).catch(err => {
showNotification('复制失败: ' + err, true);
});
}
// 显示通知
function showNotification(message, isWarning) {
notificationText.textContent = message;
notification.className = 'notification';
if (isWarning) {
notification.classList.add('warning');
}
notification.classList.add('show');
setTimeout(() => {
notification.classList.remove('show');
}, 3000);
}
// 初始化时自动提取一次
extractBtn.click();
});
</script>
<script defer src="https://static.cloudflareinsights.com/beacon.min.js/v833ccba57c9e4d2798f2e76cebdd09a11778172276447" integrity="sha512-57MDmcccJXYtNnH+ZiBwzC4jb2rvgVCEokYN+L/nLlmO8rfYT/gIpW2A569iJ/3b+0UEasghjuZH/ma3wIs/EQ==" data-cf-beacon='{"version":"2024.11.0","token":"7939e04a4baf43c8b86a560f74aac60e","server_timing":{"name":{"cfCacheStatus":true,"cfEdge":true,"cfExtPri":true,"cfL4":true,"cfOrigin":true,"cfSpeedBrain":true},"location_startswith":null}}' crossorigin="anonymous"></script>
<script defer src="https://static.cloudflareinsights.com/beacon.min.js/v833ccba57c9e4d2798f2e76cebdd09a11778172276447" integrity="sha512-57MDmcccJXYtNnH+ZiBwzC4jb2rvgVCEokYN+L/nLlmO8rfYT/gIpW2A569iJ/3b+0UEasghjuZH/ma3wIs/EQ==" data-cf-beacon='{"version":"2024.11.0","token":"7939e04a4baf43c8b86a560f74aac60e","server_timing":{"name":{"cfCacheStatus":true,"cfEdge":true,"cfExtPri":true,"cfL4":true,"cfOrigin":true,"cfSpeedBrain":true},"location_startswith":null}}' crossorigin="anonymous"></script>
</body>
</html>