Skip to content

Instantly share code, notes, and snippets.

@fire-eggs
Last active February 26, 2024 04:28
Show Gist options
  • Star 15 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save fire-eggs/5831a3ab9aa64d4275d52e76cda26ec6 to your computer and use it in GitHub Desktop.
Save fire-eggs/5831a3ab9aa64d4275d52e76cda26ec6 to your computer and use it in GitHub Desktop.
Python 3 - takes the Chrome Bookmarks file, and creates a better "Export Bookmarks" HTML page.
# Massages a Chrome bookmarks file into an HTML file.
#
# Features:
# - Folders are ordered alphabetically
# - Bookmarks are ordered alphabetically (by description)
# - Bookmarks are shown first, followed by folders
# - Folders can be expanded or collapsed. Initially collapsed.
# - Folders are indented nicely
# - A button is provided to expand/collapse all folders
#
# Setup:
# 1) Find your browser's Bookmarks file.
# 2) Copy it into the same folder as this script
# 3) Open a terminal window; change directory to this script's folder
# 4) If any of your Bookmarks have international characters, you
# will want to do the following:
# set PYTHONIOENCODING=UTF-8
# 5) python betterbookmarks.py > bookmarks.html
#
import json
import sys
import datetime
# sort a JSON entry by name, ignoring case
def sortName(val):
return val["name"].lower()
# iterate recursively through the JSON tree.
def preorder(tree,depth):
depth += 1
folders = [] # build a list of folders for later
if tree:
tree.sort(key=sortName) # bookmarks in order by name
for item in tree:
try:
childs = len(item["children"])
except:
childs = 0
if childs > 0:
folders.append(item) # output folders later
else:
# output bookmarks first
print('<DD><A HREF="'+ item["url"] + '">' + item["name"] + "</A>")
folders.sort(key=sortName) # folders in order by name
for fold in folders:
print("<details>")
print("<summary><STRONG>" + fold["name"] +"</STRONG></summary>")
print("<DL><DD>")
subtree = fold["children"]
preorder(subtree, depth)
print("</DL></details>")
JSONIN = "Bookmarks"
# Read source bookmark file
with open(JSONIN, "r", encoding='utf-8') as f:
Bookmarks = json.load(f)
print("<HTML>")
print ("""
<script>
function toggleAll() {
var all_dets = document.getElementsByTagName('details');
var det_count = all_dets.length;
for (let i=0; i < det_count; i++){
if (toggleAll.open) {
all_dets[i].setAttribute("open", "true");
} else {
all_dets[i].removeAttribute("open");
}
}
toggleAll.open = !toggleAll.open;
document.getElementById("tog").innerText = toggleAll.open ? "Expand All" : "Collapse All";
}
toggleAll.open = true;
</script>
""")
print("<BODY>")
today = datetime.date.today()
print('''<H1>Bookmarks - ''' + today.strftime("%b-%d-%Y") + '''</H1>
<button id="tog" onclick="toggleAll()">Expand All</button>
<p></p>
''')
print("<DL>")
print("<DT><STRONG>Bookmarks Bar</STRONG>")
original1 = Bookmarks['roots']['bookmark_bar']['children']
preorder(original1, 0)
print("</DL>")
print("<DL>")
print("<DT><STRONG>Other Bookmarks</STRONG>")
original2 = Bookmarks['roots']['other']['children']
preorder(original2, 0)
print("</DL>")
print("</BODY></HTML>")
@ichmoimeyo
Copy link

thank you so much - initially I was getting errors ...

File "betterbookmarks.py", line 44, in preorder
print('

<A HREF="'+ item["url"] + '">' + item["name"] + "")
KeyError: 'url'

Once I realized that it was being caused by "empty" folders in my Bookmarks file, I used Try Except as follows ...

            try:
             print('<DD><A HREF="'+ item["url"] + '">' + item["name"] + "</A>")
            except:
              item["url"] = 0

... and it generated a perfect collapsible bookmarks.html - thanks again.

@fire-eggs
Copy link
Author

Glad you liked it! Feel free to suggest any features / improvements!

@frankShih
Copy link

Hi, this script is "export bookmarks from chrome", right?
Is there any information about "import bookmarks from chrome" with python?

I am trying to create a script to sync bookmarks between all my browsers.

@fire-eggs
Copy link
Author

Yes, this is "export". The Chrome bookmarks file is JSON, so investigating JSON handling with python would be the direction I'd suggest.

In theory, composing a "new" bookmark would require adding a new entry to the dictionary produced by the parse of the bookmarks file. To produce the resulting output, use json.dump to write it. [I'm making the assumption that json.dump produces the same file as parsed by json.load.]

It might be "as simple as":

# read bookmark file 1
bookmarks1 = json.load(bookmarks_destination)
# read bookmark file 2
bookmarks2 = json.load(bookmarks_syncfrom)

# add all bookmarks from 'syncfrom' to destination
for mark in bookmarks2:
    bookmarks1.append(mark)

# write out merge result
json.dump(bookmarks1, "bookmarks_synced")

Big assumption here would be whether you can iterate across the JSON like that. Requires investigating the results from json.load and how to process it.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment