likes
comments
collection
share

如何获取链接标题?

作者站长头像
站长
· 阅读数 14

笔记类应用通常都有这样一个功能:粘贴链接时自动获取标题充当超链接文本。

这个小功能并不复杂,最直观的实现方式是发请求拿到内容,再通过 DOM 解析拿到 title

考虑到 URL 指向的不一定是网页,还有可能是各种类型的文件,加一步 content-type 判断,非网页简单返回文件名就好。

这样就有一个简单的 extractURLTitle 逻辑了。

成功
是 text/html
不是 text/html
错误
请求 URL
获取响应
检查 Content-Type
使用 DOM 解析 HTML
获取 URL 的最后一段
提取文档标题
返回标题
处理错误
返回错误

在浏览器内做跨源请求会触发 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:提供剪贴板单次修改的相关信息,和 cutcopypaste 事件相关

Notion 中并未申请系统剪贴板读写权限,因此应该是在编辑器中监听 paste 事件,通过 Clipboard Event API 做的后续操作。

ClipboardEvent 本身只有一个实例属性 clipboardData,这是一个 DataTransfer 对象。虽然规范文档中将 DataTransfer 定义为存储 drag-and-drop 操作中的拖动数据,在剪贴板操作这里 DataTransfer 大概是被定义为存储要传输的数据。那就来看下 DataTransfer 中和数据传输相关的属性和方法

  • items:存有所有传输数据项的一个列表,例如复制图文混排的内容就能产生多个数据项
    • 传输数据项(DataTransferItem)带有数据项信息
      • kind 数据种类,是 stringfile
      • type 数据项类型,一般是一个 MIME 类型
  • 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

总结

文章介绍了两种获取链接标题的途径。

一种是在服务端请求+解析网页,步骤大致是:

  1. 请求 URL 获取响应
  2. 判断 content-type
  3. 如果是 text/html,解析 DOM 获取 title
  4. 如果是其他类型,返回文件名

另一种是在前端借助剪贴板特性读取,一些应用程序在做复制操作时会往剪贴板塞入额外的信息,例如 Chrome 浏览器在地址栏复制时塞入了 URL 指向资源的基本信息。这种读取方法依赖于数据来源,存在不确定性。

或许将两种方法结合是可考虑的思路:先由前端做处理,无法解析再请求后端。

还有一点使用 GPT 的额外的收获:和 GPT 的合作中,使用者的思路决定着整体航向。人类对现实场景的准确观察分析、清晰表达,AI 的博学多闻,都是最终解决问题的关键因素,各取所长互补协作才能更高效地解决问题。