// ==UserScript==
// @name 优雅的错误页面美化
// @version 1.5
// @description 美化WebView错误页面,提供更友好的用户体验
// @author
// @match *://*/*
// @run-at document-end
// @namespace https://greasyfork.org/users/452911
// @downloadURL https://update.greasyfork.icu/scripts/561334/%E4%BC%98%E9%9B%85%E7%9A%84%E9%94%99%E8%AF%AF%E9%A1%B5%E9%9D%A2%E7%BE%8E%E5%8C%96.user.js
// @updateURL https://update.greasyfork.icu/scripts/561334/%E4%BC%98%E9%9B%85%E7%9A%84%E9%94%99%E8%AF%AF%E9%A1%B5%E9%9D%A2%E7%BE%8E%E5%8C%96.meta.js
// ==/UserScript==
(function() {
'use strict';
// 只对 chrome-error://chromewebdata/ 生效
if (window.location.href !== "chrome-error://chromewebdata/") {
return;
}
const ERROR_REGISTRY = [
/ERR_CONNECTION_REFUSED/i, /ERR_CONNECTION_TIMED_OUT/i, /ERR_INTERNET_DISCONNECTED/i,
/ERR_CONNECTION_CLOSED/i, /ERR_NAME_NOT_RESOLVED/i, /ERR_SSL_PROTOCOL_ERROR/i,
/ERR_PROXY_CONNECTION_FAILED/i, /ERR_CONNECTION_RESET/i, /ERR_CONNECTION_ABORTED/i,
/ERR_NETWORK_CHANGED/i, /ERR_ADDRESS_UNREACHABLE/i, /ERR_ADDRESS_INVALID/i,
/ERR_DNS_TIMED_OUT/i, /ERR_DNS_SERVER_FAILED/i, /ERR_SSL_VERSION_OR_CIPHER_MISMATCH/i,
/ERR_CERT_AUTHORITY_INVALID/i, /ERR_CERT_DATE_INVALID/i, /ERR_CERT_COMMON_NAME_INVALID/i,
/ERR_EMPTY_RESPONSE/i, /ERR_INVALID_RESPONSE/i, /ERR_CONTENT_LENGTH_MISMATCH/i,
/ERR_TUNNEL_CONNECTION_FAILED/i, /ERR_TIMED_OUT/i, /ERR_FAILED/i, /ERR_ACCESS_DENIED/i,
/ERR_BLOCKED_BY_CLIENT/i, /ERR_BLOCKED_BY_RESPONSE/i, /ERR_TOO_MANY_REDIRECTS/i,
/ERR_UNSAFE_PORT/i, /ERR_UNSAFE_REDIRECT/i, /DNS_PROBE_FINISHED_NO_INTERNET/i,
/DNS_PROBE_FINISHED_NXDOMAIN/i, /DNS_PROBE_STARTED/i, /PR_CONNECT_RESET_ERROR/i,
/PR_END_OF_FILE_ERROR/i, /NS_ERROR_NET_TIMEOUT/i, /NS_ERROR_CONNECTION_REFUSED/i,
/NS_ERROR_NET_RESET/i, /NS_ERROR_PROXY_CONNECTION_REFUSED/i, /ERR_FILE_NOT_FOUND/i,
/ERR_REQUEST_RANGE_NOT_SATISFIABLE/i, /ERR_INVALID_HTTP_RESPONSE/i, /ERR_SSL_BAD_RECORD_MAC_ALERT/i,
/ERR_DISALLOWED_URL_SCHEME/i, /ERR_UNKNOWN_URL_SCHEME/i
];
const MessageEngine = (code) => {
let conf = { type: '网络错误', desc: '无法访问此网站,请检查网络连接', help: '
检查数据流量或 Wi-Fi 连接尝试关闭并重新开启飞行模式' };
if (/TIMED_OUT|TIMEOUT/.test(code)) {
conf = { type: '连接超时', desc: '服务器响应时间过长', help: '检查网络信号是否稳定尝试刷新页面或稍后再试检查防火墙或代理服务器设置' };
} else if (/REFUSED/.test(code)) {
conf = { type: '连接被拒绝', desc: '目标服务器拒绝了连接请求', help: '核对网址拼写是否正确该网站可能暂时关闭或维护检查本地防火墙拦截记录' };
} else if (/NAME_NOT_RESOLVED|NXDOMAIN|DNS_/.test(code)) {
conf = { type: 'DNS 解析失败', desc: '找不到服务器的 IP 地址', help: '检查网址是否拼写错误尝试修改 DNS 为 223.5.5.5 或 8.8.8.8清除浏览器 DNS 缓存' };
} else if (/DISCONNECTED|NO_INTERNET/.test(code)) {
conf = { type: '网络已断开', desc: '当前未连接到互联网', help: '检查网线、调制解调器和路由器重新连接 Wi-Fi 或移动数据检查是否欠费停机' };
} else if (/CLOSED|RESET|ABORTED/.test(code)) {
conf = { type: '连接中断', desc: '与服务器的连接意外丢失', help: '网络环境切换可能导致此问题尝试重新加载网页检查 VPN 或加速器连接状态' };
} else if (/SSL_|CERT_|PROTOCOL|INSECURE/.test(code)) {
conf = { type: '安全连接失败', desc: '网页使用了不安全的证书或协议', help: '检查系统日期和时间是否准确该网站证书可能已过期或不可信尝试清除 HSTS 状态' };
} else if (/PROXY_/.test(code)) {
conf = { type: '代理错误', desc: '代理服务器连接异常', help: '检查系统或浏览器的代理设置尝试禁用 VPN 或第三方代理工具' };
} else if (/ACCESS_DENIED|BLOCKED/.test(code)) {
conf = { type: '访问受阻', desc: '请求被客户端或服务器拦截', help: '检查广告过滤插件设置该页面可能需要特定的访问权限尝试清除 Cookie 后重新登录' };
} else if (/_TOO_MANY_|REDIRECTS/.test(code)) {
conf = { type: '重定向过多', desc: '网页导致了过多的重定向循环', help: '尝试清除该网站的 Cookie该网站可能配置错误,请联系网站管理员' };
} else if (/ADDRESS_UNREACHABLE|ADDRESS_INVALID/.test(code)) {
conf = { type: '地址无效', desc: '无法找到通往目标服务器的路径', help: '检查输入的网址是否包含错误 IP尝试切换网络环境' };
} else if (/FILE_NOT_FOUND/.test(code)) {
conf = { type: '文件不存在', desc: '无法找到请求的文件资源', help: '检查本地路径或 URL 拼写该文件可能已被移动或删除' };
} else if (/SCHEME/.test(code)) {
conf = { type: '协议不支持', desc: '不支持的 URL 方案或协议', help: '请检查 URL 开头的协议是否正确某些链接需要特定的 App 才能打开' };
}
return conf;
};
const VisualCore = {
render(data) {
const root = document.createElement('div');
const shadow = root.attachShadow({ mode: 'open' });
shadow.innerHTML = `
${data.type}
无法打开网页
${data.desc}
建议:
ERROR: ${data.code}
URL: ${data.url}
`;
this.initEvents(shadow);
document.body.appendChild(root);
},
initEvents(shadow) {
shadow.getElementById('retry').onclick = () => location.reload();
shadow.getElementById('back').onclick = () => history.length > 1 ? history.back() : window.close();
shadow.getElementById('info-btn').onclick = function() {
const panel = shadow.getElementById('panel');
const isShow = panel.style.display === 'block';
panel.style.display = isShow ? 'none' : 'block';
this.innerText = isShow ? '查看故障详情' : '收起详细信息';
};
}
};
const Initializer = {
applied: false,
getExtractedUrl() {
let url = location.href;
const html = document.documentElement.innerHTML;
// 提取URL逻辑
const urlPatterns = [
/位于\s*([^<]+)<\/strong>/i,
/位于\s*([^<]+)<\/b>/i
];
for (const pattern of urlPatterns) {
const match = html.match(pattern);
if (match && match[1]) {
url = match[1].trim();
return url;
}
}
const urlMatch = html.match(/https?:\/\/[^\s<>"']+/i);
if (urlMatch) {
url = urlMatch[0];
}
return url;
},
run() {
if (this.applied || !document.body) return;
// 只处理 chrome-error://chromewebdata/ 页面
if (window.location.href !== "chrome-error://chromewebdata/") return;
const content = (document.body.textContent + document.title).toUpperCase();
// 检查是否为错误页面
if (!ERROR_REGISTRY.some(r => r.test(content))) return;
this.applied = true;
// 提取错误代码
const codeMatch = document.body.textContent.match(/(ERR_[A-Z_]+|DNS_[A-Z_]+|NS_ERROR_[A-Z_]+)/i);
const errorCode = codeMatch ? codeMatch[0].toUpperCase() : 'ERR_FAILED';
const info = MessageEngine(errorCode);
// 使用新逻辑获取URL
const realUrl = this.getExtractedUrl();
document.documentElement.innerHTML = '';
VisualCore.render({ code: errorCode, url: realUrl, ...info });
}
};
new MutationObserver(() => Initializer.run()).observe(document.documentElement, { childList: true, subtree: true });
window.addEventListener('load', () => Initializer.run());
setTimeout(() => Initializer.run(), 250);
})();