如何获取链接标题?
笔记类应用通常都有这样一个功能:粘贴链接时自动获取标题充当超链接文本。
这个小功能并不复杂,最直观的实现方式是发请求拿到内容,再通过 DOM 解析拿到 title
。
考虑到 URL 指向的不一定是网页,还有可能是各种类型的文件,加一步 content-type
判断,非网页简单返回文件名就好。
这样就有一个简单的 extractURLTitle
逻辑了。
在浏览器内做跨源请求会触发 CORS block,那就转移给服务端去做。不管是用 Python 还是 NodeJS,或者加一些对其他类型的文件 (pdf、doc 等等)做深入解析,和 GPT 聊一聊,这是它擅长的事。
好了,一个简单的请求获取的方案完成了。但是在 Notion 中发现一个奇怪的事,当我粘贴链接,Notion 并未发出解析网址相关的请求;并且必须在浏览器打开链接后,Notion 才能成功获取标题。
我带着疑惑询问 GPT,TA 告诉我「Notion 使用 Open Graph 协议在不提出请求的情况下提取 URL 标题。当您向 Notion 页面添加 URL 时,它会自动获取与 URL 关联的元数据,包括标题、描述和缩略图图像(如果有的话)」。但是获取元数据不还是得请求原链接么?这个回答应该不准确。
网页信息绝不可能无中生有,很有可能是存在剪贴板中。带着这个思路,从浏览器地址栏复制再粘贴,成功解析出标题;从网页正文复制再粘贴,解析标题失败。所以重点在剪贴板。
剪贴板读取相关的 API 有两个:
Clipboard
:提供接口异步读写系统剪贴板,通过navigator.clipboard
调用,需要申请"clipboard-read"
和"clipboard-write"
权限ClipboardEvent
:提供剪贴板单次修改的相关信息,和cut
、copy
、paste
事件相关
Notion 中并未申请系统剪贴板读写权限,因此应该是在编辑器中监听 paste
事件,通过 Clipboard Event API
做的后续操作。
ClipboardEvent
本身只有一个实例属性 clipboardData
,这是一个 DataTransfer
对象。虽然规范文档中将 DataTransfer
定义为存储 drag-and-drop 操作中的拖动数据,在剪贴板操作这里 DataTransfer
大概是被定义为存储要传输的数据。那就来看下 DataTransfer
中和数据传输相关的属性和方法
items
:存有所有传输数据项的一个列表,例如复制图文混排的内容就能产生多个数据项- 传输数据项(DataTransferItem)带有数据项信息
kind
数据种类,是string
或file
type
数据项类型,一般是一个 MIME 类型
- 传输数据项(DataTransferItem)带有数据项信息
files
:传输的文件列表 FileList,例如从本地文件系统复制文件types
:返回写入时设置的所有数据格式getData(type)
:返回某个数据格式对应的值
数据格式和对应的值是在复制时由所处的应用程序定义的,应用程序可以调用封装好的系统接口往剪贴板里放额外的信息,来看下浏览器地址栏都给了什么信息。
<!DOCTYPE html>
<html>
<head>
<title>Extract Page Title</title>
</head>
<body>
<input type="text" id="myInput">
<script>
const input = document.getElementById('myInput');
input.addEventListener('paste', (event) => {
const clipboardData = event.clipboardData;
console.log("types", clipboardData.types);
clipboardData.types.forEach(type => {
console.log(`"${type}"` , clipboardData.getData(type))
});
});
</script>
</body>
</html>
在地址栏复制时,Chrome 浏览器往剪贴板塞了一个
text/link-preview
类型的数据,包含以下字段
{
"domain": "feishu.cn",
"preferred_format": "text/html;content=titled-hyperlink",
"title": "飞书——先进企业协作与管理平台,一站式无缝办公协作,团队上下对齐目标,全面激活组织和个人。先进团队,先用飞书。",
"type": "website",
"url": "https://www.feishu.cn/"
}
所以,要实现本地获取链接标题,可以监听 paste
事件,尝试获取 event.clipboardData.getData("text/link-preview")?.title
总结
文章介绍了两种获取链接标题的途径。
一种是在服务端请求+解析网页,步骤大致是:
- 请求 URL 获取响应
- 判断
content-type
- 如果是
text/html
,解析 DOM 获取title
- 如果是其他类型,返回文件名
另一种是在前端借助剪贴板特性读取,一些应用程序在做复制操作时会往剪贴板塞入额外的信息,例如 Chrome 浏览器在地址栏复制时塞入了 URL 指向资源的基本信息。这种读取方法依赖于数据来源,存在不确定性。
或许将两种方法结合是可考虑的思路:先由前端做处理,无法解析再请求后端。
还有一点使用 GPT 的额外的收获:和 GPT 的合作中,使用者的思路决定着整体航向。人类对现实场景的准确观察分析、清晰表达,AI 的博学多闻,都是最终解决问题的关键因素,各取所长互补协作才能更高效地解决问题。
转载自:https://juejin.cn/post/7240042688313114682