浏览器有个实用的功能,但是可能用的频率不高,就是书签/收藏的导入和导出,因为现在一般浏览器都有云同步功能,所以这个功能存在感不强。

浏览器书签是可以跨不同的浏览器导入的,所以意味着导出的文件肯定是有一个规范的,我简单搜了一下没有搜到,可能是各家约定俗成的规范,并没有一个正式的标准。

通用的数据交换格式有很多,比如xml、json、yaml,json应该是使用最广泛的,因为易于解析和存储,尺寸也不大,所以很适合浏览器书签的导出,但是,实际上现代浏览器导出的书签文件是html文件。原因不详,也没有搜到相关信息,我猜测原因可能是html文件相对于json来说,普通用户更为熟悉,其次,html文件可以直接使用浏览器打开,当然,json文件也可以使用浏览器打开,但是可能直接点击的时候默认是用文本编辑器打开的,另外它们在浏览器的呈现方式也不一样,html显示的是一个普通的带有一堆超链接的页面,就是一个有点丑的网页,而json打开有点类似源码,不太友好,因为一般用户导出书签就是为了在另一个浏览器导入,所以屏蔽细节并没有什么问题。

html和xml是类似的,所以解析和传输也很简单,接下来看一下实例:

基本结构如上,每个文件夹下都有个书签,导出的书签源码如下:

简单分析一下:

1.标签字母都是大写

2.DOCTYPE声明和普通HTML页面不同

3.使用DL和DT来组织书签,DL代表一个文件夹的内容列表,DT代表一个内容,可能是书签也可能是文件夹,文件夹的话会有一个H3标签来表示书签的名字,书签的话就是直接跟一个A标签,DL标签后都跟了一个小写的p标签,有部分标签没有闭合

4.H1标签之前的都和书签内容没有什么关系

5.文件夹名称H3标签和超链接A标签都有ADD_DATELAST_MODIFIED来保存时间信息,该属性不存在也不影响

6.文件夹名称H3标签的属性PERSONAL_TOOLBAR_FOLDER来表示该文件夹下的内容是否显示到浏览器的工具栏,否则会默认放到浏览器的其他文件夹里,但也不一定,有的浏览器会有自己的行为

7.网页的标题icon会转换为base64格式放到ICON属性上,这个属性不存在也不影响

html其实就是普通字符串,所以可以手动生成,常见于一些导航网站和网址收藏工具的导出功能,如五花八门导航(http://lxqnsys.com/d),有一个需要注意的地方,就是html字符串必须格式化带换行和缩进,下图这种压缩过的是不行的:

生成方式也很简单,书签是树结构,所以递归循环拼接即可。

先看一下书签数据的格式,忽略时间和icon:

let bookmarks = [{name: '',// 文件夹或书签名字toolbar: true,// 是否显示到工具栏folder: true,// 是否是文件夹children: [{name: '',folder: true,children: []},{name: '',// 书签名称url: ''// 书签url}]}
]

使用ES6的话可以直接使用模板字符串``来带换行的拼接,很方便:

function createBookmarksStr (bookmarks) {let str = `<!DOCTYPE NETSCAPE-Bookmark-file-1><!-- This is an automatically generated file.It will be read and overwritten.DO NOT EDIT! --><META HTTP-EQUIV="Content-Type" CONTENT="text/html; charset=UTF-8"><TITLE>Bookmarks</TITLE><H1>Bookmarks</H1><DL><p>`let loop = (root) => {let str = ''root.forEach((item) => {if (item.folder) {str += `<DT><H3 ${item.toolbar ? `PERSONAL_TOOLBAR_FOLDER="true"` : ''}>${item.name}</H3><DL><p>`str += loop(item.children)str += `</DL><p>`} else {str += `<DT><A HREF="${item.url}">${item.name}</A>`}})return str}str += loop(bookmarks)str += `</DL><p>`return str
}

ES6之前的就需要显式的拼接上换行符:

function createBookmarksStr (bookmarks) {var str = '<!DOCTYPE NETSCAPE-Bookmark-file-1>\n<!-- This is an automatically generated file.It will be read and overwritten.DO NOT EDIT! -->\n<META HTTP-EQUIV=\"Content-Type\" CONTENT=\"text/html; charset=UTF-8\">\n<TITLE>Bookmarks</TITLE>\n<H1>Bookmarks</H1>\n<DL>\n\t<p>\n\t\t<DT>\n\t\t\t<H3 ADD_DATE=\"1568796074\" LAST_MODIFIED=\"1601707819\" PERSONAL_TOOLBAR_FOLDER=\"true\">\u4E66\u7B7E\u680F</H3>\n\t\t\t<DL>\n\t\t\t\t<p>\n\t\t\t\t\t'var loop = function (root) {var str = ''root.forEach(function (item) {if (item.folder) {str += '<DT>\n\t\t\t\t\t\t<H3 '+ (item.toolbar ? 'PERSONAL_TOOLBAR_FOLDER="true"' : '') +'>'+item.name+'</H3>\n\t\t\t\t\t\t<DL>\n\t\t\t\t\t\t\t<p>\n\t\t\t\t\t\t\t\t'str += loop(item.children)str += '</DL>\n\t\t\t\t\t\t<p>\n\t\t\t'} else {str += '<DT><A HREF=\"'+item.url+'\">'+item.name+'</A>\n\t\t\t\t\t\t\t\t'}})return str}str += loop(bookmarks)str += '</DL>\n\t\t\t<p>\n</DL>\n<p>'return str
}

看完了如何生成,接下来看一下如何解析,解析和拼接类似,也是通过深度优先进行遍历,只是会有一些特征判断。字符串如何转化成一棵树,最简单的肯定是先转换为DOM元素,然后再通过操作DOM的api来进行遍历,有一些库可以用来做这件事,不过这里直接用的是iframe

function getBookmarksStrRootNode (str) {// 创建iframelet iframe = document.createElement('iframe')document.body.appendChild(iframe)iframe.style.display = 'none'// 添加书签dom字符串iframe.contentWindow.document.documentElement.innerHTML = str// 获取书签树根节点return iframe.contentWindow.document.querySelector('dl')
}
function analysisBookmarksStr(str) {let root = getBookmarksStrRootNode(str)
}

看一下转换的结果:

书签DOM字符串:

转换后的DOM节点:

获取到书签树的根节点,接下来递归遍历即可:

function walkBookmarksTree (root) {let result = []// 深度优先遍历let walk = (node, list) => {let els = node.childrenif (els && els.length > 0) {for (let i = 0; i < els.length; i++) {let item = els[i]// p标签或h3标签直接跳过if (item.tagName === 'P' || item.tagName === 'H3') {continue}// 文件夹不用创建元素if (item.tagName === 'DL') {walk(els[i], list)} else {// DT节点let child = null// 判断是否是文件夹let children = item.childrenlet isDir = falsefor(let j = 0; j < children.length; j++) {if (children[j].tagName === 'H3' || children[j].tagName === 'DL') {isDir = true}}// 文件夹if (isDir) {child = {name: item.tagName === 'DT' ? item.querySelector('h3') ? item.querySelector('h3').innerText : '' : '',folder: true,children: []}walk(els[i], child.children)} else {// 书签let _item = item.querySelector('a')child = {name: _item.innerText,url: _item.href}}list.push(child)}}}}walk(root, result)return result
}
function analysisBookmarksStr(str) {let root = getBookmarksStrRootNode(str)let result = walkBookmarksTree(root)
}

最后解析的结果:

搞定收工,赶紧去试试吧。

浅析浏览器书签的导入和导出相关推荐

  1. xml显示浏览器标签_浅析浏览器书签的导入和导出

    浏览器有个实用的功能,但是可能用的频率不高,就是书签/收藏的导入和导出,因为现在一般浏览器都有云同步功能,所以这个功能存在感不强. 浏览器书签是可以跨不同的浏览器导入的,所以意味着导出的文件肯定是有一 ...

  2. 火狐怎么导入收藏夹_火狐浏览器怎么导入及导出书签?导入及导出书签的方法说明...

    IE问题解决办法文章由小编整理发出,内容真实有效,欢迎提出您的意见IE系列文章由小编在互联网中整理并且发出,内容保障真实健康. 火狐浏览器是目前非常流行的网页浏览器,使用人数非常多,尤其是从事IT行业 ...

  3. chrome浏览器书签快速导入导出

    1.从chrome导出标签 导出到桌面生成.html格式文件 2.导入书签到chrome 选择步骤1中导出的html,在书签管理器中导入即可

  4. 轻松备份专业版怎么迁移系统_如何轻松备份和迁移浏览器书签

    轻松备份专业版怎么迁移系统 Most of our browser data isn't too important-cookies expire, and histories eventually ...

  5. 将搜狗浏览器收藏夹导入到IE、Firefox、Chrome

    搜狗浏览器收藏夹导入.导出的文件格式是.xml,与IE.Firefox.Chrome等的导入.导出使用的.htm格式不同.于是要把搜狗浏览器收藏夹导入到IE.Firefox.Chrome也就需要做一些 ...

  6. 火狐浏览器如何导入和导出书签收藏夹

    火狐浏览器怎么导入和导出书签收藏夹?火狐浏览器是一款功能强大的浏览器,在使用浏览器时想要把书签收藏夹导出或导出到另外一个浏览器要怎么操作呢,下面就给大家分享具体步骤. 1.打开火狐浏览器,点击左上角& ...

  7. 谷歌浏览器导出书签、导入书签,html 格式 。QQ浏览器导出书签、导入书签,html 格式

    谷歌浏览器 导出: 1.打开谷歌浏览器 2.点击浏览器右上角的管理--书签 3.在书签里点击"书签管理器" 4.右上角的管理--导出书签(html格式) 导入: 1.进入" ...

  8. 浏览器收藏夹(书签)导入导出

    文章目录 前言 一.操作步骤 1.ME浏览器导出收藏夹 2.将ME浏览器导出的收藏夹导入到谷歌浏览器 总结 前言 平时或工作中我们经常会有这样一些烦恼, 重装系统后或变更浏览器后,如何将之前浏览器我们 ...

  9. html收藏导入浏览器,分享星愿浏览器导入和导出收藏夹方法

    软件安装:猎豹浏览器 装机大全致力于收录最值得您拥有的精品应用,第一时间武装您的电脑变身电脑达人 我们将为您奉上 更贴心的分类方式:无论您喜欢音乐.视频, 还是热衷教程.资讯, 精准的分类方便您在装机 ...

  10. 谷歌浏览器导入导出书签,导入导出密码

    导出导入书签 1.打开书签管理器 一般书签上面右键就能看到书签管理器 2.打开导入导出菜单 进入书签管理器后,右上角,三个竖着的小点,如下 点开如下图 3.导出导入书签 上图,选择导出书签,导出的是一 ...

最新文章

  1. Git搭建自己的网站服务器(Linux)
  2. 如何用UE(UltraEdit)删除重复行?--转
  3. Laravel大型项目系列教程(一)
  4. 周末随笔 | 问好一个问题,有的放矢
  5. matlab读取正则找科学,MATLAB常用正则表达式记录
  6. Apollo进阶课程㉘丨Apollo控制技术详解——基于模型的控制方法
  7. OpenCV与图像处理学习十二——图像形状特征之HOG特征
  8. 《CCNA无线640-722认证考试指南》——5.4节其他无线拓扑
  9. linux目录大小从大到小,linux系统下如何将当前目录下的文件从小到大排列
  10. linux系统磁盘的分配空间不足,Linux系统磁盘空间不足解决办法
  11. ubuntu mysql下载64位下载_ubuntu mysql下载|
  12. [渝粤教育] 天水师范学院 matlab电子仿真与应用 参考 资料
  13. 完整java开发中JDBC连接数据库代码和步骤[申明:来源于网络]
  14. c语言实验报告1华科,华科操作系统实验报告
  15. html中src中的url,HTML 中的 href\src\url
  16. Manitest: Are classifiers really invariant?论文解读
  17. PCI-E 1x, 4x, 8x, 16x 接口定义
  18. 你的账户配置为阻止使用计算机,Win10打开软件提示为了对电脑进行保护,已经阻止此应用解决方法...
  19. mac 苹果系统安装pygame环境插件
  20. 基于项目的协同过滤推荐算法单机版代码实现(包含输出电影-用户评分矩阵模型、项目相似度、推荐结果、平均绝对误差MAE)

热门文章

  1. 化繁为简 “云桥OneBridge”让IT运维事半功倍
  2. 扫描枪取消回车二维码_扫码枪设置自动回车方法步骤,条码扫描枪不自动回车怎么办...
  3. CentOS7安装MySQL8报错mariadb-libs is obsoleted by mysql-community-libs-8.0.xx-1.el7.x86_64
  4. AI npc会做成为游戏制作人的梦吗?
  5. 基于Tensorflow实现声音分类
  6. 【读书笔记】期权交易策略(2)—— 差价策略
  7. 企业微信员工离职后,还能看聊天记录吗?
  8. 【Linux】一步一步学Linux——stty命令(243)
  9. 查看Win10是否永久激活
  10. 硕士论文查重原理与快速通过的七大方法