缘起
我发现浏览器地址栏中显示的,和我将其复制粘贴到编辑器中的内容不同。
比如地址栏显示的是,https://ds63.eu.org/2022/村上春树
,但当我粘贴到Vscode后,却是https://ds63.eu.org/2022/%E6%9D%91%E4%B8%8A%E6%98%A5%E6%A0%91/
编码与解码
我之前只知道形如%E6%9D%91
是url编码,但没详细了解过。
根据百分号编码 - Wikiwand的介绍,过程如下:
- 将每个字符按照 UTF-8 编码规则转换为字节序列
- 将每个字节编码为 % 后跟两个十六进制数字
original_string = "村上春树"
utf8_string = original_string.encode('utf-8')
print(utf8_string)
#b'\xe6\x9d\x91\xe4\xb8\x8a\xe6\x98\xa5\xe6\xa0\x91'
hex_utf8_string = '%'.join([f'{b:02X}' for b in utf8_string])
print(hex_utf8_string)
#E6%9D%91%E4%B8%8A%E6%98%A5%E6%A0%91
- 实际使用时可以用
urllib.parse
这个库
# 编码
from urllib.parse import quote,unquote
original_url = "https://ds63.eu.org/2022/村上春树"
encoded_url = quote(original_url, safe=':/')
print(encoded_url) #https://ds63.eu.org/2022/%E6%9D%91%E4%B8%8A%E6%98%A5%E6%A0%91/
#解码
decoded_url = unquote(encoded_url)
print(decoded_url) #https://ds63.eu.org/2022/村上春树/
显示与实际复制
那浏览器是如何实现用户看到的与实际复制不同的呢,我猜测可能是这样的:
<div id="userFriendlyUrl" oncopy="handleCopy()">
https://ds63.eu.org/2022/村上春树
</div>
<script>
function handleCopy() {
// 获取用户友好的URL
var userFriendlyUrl = document.getElementById("userFriendlyUrl").innerText;
// 对URL进行URL编码
var encodedUrl = encodeURIComponent(userFriendlyUrl);
// 创建一个文本区域元素,设置其值为编码后的URL
var textarea = document.createElement("textarea");
textarea.value = encodedUrl;
// 将文本区域元素添加到页面中
document.body.appendChild(textarea);
// 选中文本
textarea.select();
textarea.setSelectionRange(0, 99999); // 兼容移动设备
// 复制文本到剪贴板
document.execCommand("copy");
// 移除文本区域元素
document.body.removeChild(textarea);
// 阻止默认复制事件,避免复制原始文本
event.preventDefault();
//alert("URL copied: " + encodedUrl);
}
</script>
国际化域名
我上述的例子并没有考虑到国际化域名。
具体可参看国际化域名和Punycode编码。
意外收获
我之前就好奇汉字到底有多少个,看中文字符集 Unicode 编码范围,发现可能应该不到十万。
ps: 看中日韩统一表意文字 - 维基百科,自由的百科全书,还是觉得很混乱。不少是历史遗留下来的问题,所以我先前的估算显然是有问题的。
之后我又查了些资料,发现现在关于汉字的数量仍没有定论,可以说是众说纷纭。
延伸
在写这篇博客之后,我才注意到浏览器的地址栏原来有如此多的功能:
地址栏预测: 当用户输入地址栏时,浏览器会根据用户的浏览历史、收藏夹和搜索历史等信息提供地址栏预测。这有助于用户快速访问常用站点。
搜索建议: 地址栏还充当搜索栏,用户可以直接在其中输入搜索关键字。浏览器通常会基于用户的输入和搜索历史,提供搜索建议。
安全指示: 浏览器通常在地址栏中显示有关连接安全性的信息,如锁定图标或"安全"标签,以指示连接的加密状态。
国际化域名(IDN)支持: 浏览器会对国际化域名进行处理,确保它们在地址栏中正确显示,并在需要时进行Punycode编码。
复制与粘贴: 用户在地址栏中复制时,通常会复制显示的用户友好的URL,而不是编码后的URL。这是为了提高用户的可理解性。
这里打算给自己挖个坑,想试着自己实现一个地址栏。