我的 Chrome 书签太乱了。所以我将它导出,并决定编写一个 Python 程序来清理我的书签。例如:按关键字对它们进行排序。
我找到了美丽的汤。但问题是,导出文件使用的是网景书签文件格式,而不是标准的 XML。Beautiful Soup 会尝试将它们转换为标准的 XTML 格式。Chrome 将无法读取它。
还有其他解决方案吗?
我的 Chrome 书签太乱了。所以我将它导出,并决定编写一个 Python 程序来清理我的书签。例如:按关键字对它们进行排序。
我找到了美丽的汤。但问题是,导出文件使用的是网景书签文件格式,而不是标准的 XML。Beautiful Soup 会尝试将它们转换为标准的 XTML 格式。Chrome 将无法读取它。
还有其他解决方案吗?
默认情况下,Chrome 将您的书签存储为 JSON,例如:
C:\Users\user\AppData\Local\Google\Chrome\User Data\Default\Bookmarks
对于 Linux 用户:
~/.config/chrome/Default/Bookmarks
(当然,此文件的位置会因您的平台而异。)
您可能会发现此文件比 HTML 导出更容易操作。
我也有同样的问题。现在我正在做一个 Python 书签工具包,只是为了从 Chrome 中清理我凌乱的书签。
github 上的书签:https ://github.com/allengaller/bookmarkit
我认为用 Chrome 定位书签文件对你/我没有帮助。除非您将 JSON 文件解析为 Dict(我看到您对此提出了另一个问题,并且我认为您已经留下了 SGML 书签文件。)
我的解决方案是:
使用 CLI 管理书签是死路一条,因为对于真正需要一个工具来管理书签的人来说这是一个非常艰难的进步(他们中的大多数人像我一样拥有 10M+ 的书签文件),我将使用 PyGTK 或 PyQT 来提供简单的基于拖放的 GUI。
关于 BS 更改您的文件:忘记 BS 将对您的书签文件所做的更改。每次解析完文件,生成一个NETSCAPE-BOOKMARK文件,不使用原始文件(即使它没有被改变)
试试 ElementTree 库。
请参见此处:http ://docs.python.org/library/xml.etree.elementtree.html
我认为解析 SGML 比直接更改 Chrome 正在使用的 JSON 文件更安全。因为像我这样的重度用户非常重视我们的数据,我宁愿小心导出,导入我的 Toolkit,完成我的工作,然后再导入 Chrome。这种进展最好是明确的。
我想出了如何用 Node.js 做到这一点。只需安装cheerio (npm install -Scheerio) 并通过环境变量或命令行参数添加 inputFile 和 outputFile 的名称。这是我的解决方案:
const fs = require('fs')
const path = require('path')
const cheerio = require('cheerio')
const inputFile = process.env.INPUT || process.argv[2] || 'bookmarks.html'
const outputFile = process.env.OUTPUT || process.argv[3] || 'bookmarks.json'
const inputFilePath = path.resolve(inputFile)
const outputFilePath = path.resolve(outputFile)
fs.readFile(inputFilePath, { encoding: 'utf8' }, (error, data) => {
if (error)
return console.error(error)
const $ = cheerio.load(data)
function parseTerm(element, out) {
const item = {}
if (element.name === 'dt') {
parseTerm($(element).children(':not(p)').first().get()[0], out)
} else if (element.name === 'h3') {
item.title = $(element).text()
item.type = 'folder'
item.updated = $(element).attr('last_modified')
item.children = []
out.push(item)
parseList($(element).next(), item.children)
} else if (element.name === 'a') {
item.title = $(element).text()
item.type = 'link'
item.added = $(element).attr('add_date')
item.href = $(element).attr('href')
item.icon = $(element).attr('icon')
out.push(item)
}
}
function parseList(list, out) {
list.children(':not(p)').each(function (index) {
parseTerm(this, out)
})
}
const out = []
parseList($('dl').first(), out)
fs.writeFile(outputFilePath, JSON.stringify(out, null, 2), error => {
if (error)
return console.error(error)
console.log('Success!')
})
})