Skip to content

Instantly share code, notes, and snippets.

@drdrang
Last active July 20, 2020 07:07
Show Gist options
  • Star 2 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save drdrang/dfc04bf76bd0d576a69d9280385c36cf to your computer and use it in GitHub Desktop.
Save drdrang/dfc04bf76bd0d576a69d9280385c36cf to your computer and use it in GitHub Desktop.
Extract feeds from Safari and print them as OPML.
#!/usr/bin/python
from plistlib import readPlist
from os import environ
from cgi import escape
# OPML template with header and footer.
opml = '''<?xml version="1.0"?>
<opml version="1.1">
<head>
<title>Feeds Imported from Safari</title>
</head>
<body>
{}
</body>
</opml>
'''
# Outline template for each item.
outline = ' <outline text="{}" htmlUrl="{}" xmlUrl="{}" type="rss" />'
# read and parse the WebFeedSources.plist file from ~/Library/Safari.
plistfile = environ['HOME'] + '/Library/Safari/WebFeedSources.plist'
wfsources = readPlist(plistfile)
# Create the body of the OPML file from WebFeedSources as a list.
# Because WebFeedSources may contain Unicode and XML special characters,
# encode the data and turn the special characters into entities.
body = []
for feed in wfsources:
try:
title = feed['Title'].encode('utf8')
except KeyError:
title = 'Untitled'
try:
htmlURL = feed['SourceURL'].encode('utf8')
except KeyError:
htmlURL = ''
try:
xmlURL = feed['FeedURL'].encode('utf8')
except KeyError:
xmlURL = ''
fields = [ escape(f, True) for f in (title, htmlURL, xmlURL) ]
body.append(outline.format(*fields))
# Output the entire OPML.
print opml.format('\n'.join(body))
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment