jetxee / deliciousBlog (http://nix-tips.blogspot.com/2009/09/bookmark-your-blog-on-delicious.html)

Take all published posts from the exported blogger (blogspot) XML and bookmark them on Delicious with the same tags. A python/shell script.

Clone this repository (size: 3.1 KB): HTTPS / SSH
$ hg clone http://bitbucket.org/jetxee/deliciousblog/
commit 0: 5d5a38128dbd
branch: default
tags: tip
Initial commit. Works for me.
jet...@gmail.com
6 months ago
deliciousBlog / deliciousBlog.py
r0:5d5a38128dbd 122 loc 4.3 KB embed / history / annotate / raw /
#!/usr/bin/env python
# vim: set fileencoding=utf-8 :

import sys
from os.path import basename
from subprocess import Popen, PIPE
from pydelicious import DeliciousAPI

# Dependencies:
# 0. posix system (shell and pipes)
# 1. pydelicious (http://code.google.com/p/pydelicious/)
# 2. xmlstarlet (http://xmlstar.sf.net/)

usage = """Usage:

%(prog)s blog-DD-MM-YYY.xml user pass [ --dry-run ]
%(prog)s --help

    Take all published posts from the exported blogger XML and bookmark them
    on Delicious with the same tags. Username and password should be valid
    Delicious credentials.
"""

# Use xmlstartlet to extract everything we need from blog XML export file:
# title, link and tags from only published posts
xmlscript = """xmlstarlet sel -N atom="http://www.w3.org/2005/Atom" -T -t \\
-m "//atom:feed/atom:entry/atom:category[@term='http://schemas.google.com/blogger/2008/kind#post']/../atom:link[@rel='alternate'][@type='text/html']/.." \\
-v "atom:title" -o '|' \\
-m "atom:link[@type='text/html'][@rel='alternate']" \\
-v '@href' -o '|' \\
-m "../atom:category[@scheme='http://www.blogger.com/atom/ns#']" \\
-v '@term' -o ',' \\
-b -n '%(blogxml)s'
"""

# posts with any of the skip_tags should never be bookmarked
skip_tags = set([ u"личное", u"personal", u"private", u"me" ])

def unpacktuples(f):
    "Unpack a tuple of function arguments automatically."
    def run(*args):
        if len(args) == 1 and isinstance(args,(tuple)):
            return f(*(args[0])) # unpack tuple
        else:
            f(*args) # call as is
    return run

@unpacktuples
def fix_post(title, url, tagstring):
    def fix_tags(s):
        tags = s.split(',')
        return ' '.join([ tag.replace(" ","_") for tag in tags ])
    return {"title":title,"url":url,"tags":fix_tags(tagstring)}

def usage_exit(exitcode=0):
    print >>sys.stderr, (usage % {"prog": basename(sys.argv[0])})
    sys.exit(exitcode)

if __name__ == '__main__':
    # command line arguments
    if "--help" in sys.argv or "-h" in sys.argv or "--usage" in sys.argv:
        usage_exit()
    if "--dry-run" in sys.argv:
        do_nothing = True
        sys.argv.remove("--dry-run")
    else:
        do_nothing = False

    try:
        blogxml, username, passwd = sys.argv[1:1+3]
    except ValueError:
        print >>sys.stderr, "Wrong number of arguments."
        usage_exit(1)

    # run script and read result from pipe
    p = Popen(xmlscript%{'blogxml':blogxml}, shell=True, stdout=PIPE)
    input = p.stdout.readlines()
    rc = p.stdout.close()
    if rc != None and rc % 256:
        print >>sys.stderr, "XML processing script failed."
        sys.exit(rc % 256)

    # select and preprocess post data
    posts = [ fix_post((p.decode("utf-8").split("|"))) for p in input ]
    # remove posts with skip_tags
    not_skip = lambda ts: len ( set(ts.split()) & skip_tags ) == 0
    posts = [ p for p in posts if not_skip(p["tags"]) ]

    # post to delicious
    dAPI = DeliciousAPI(username, passwd, codec='utf-8')
    for p in posts:
        if do_nothing:
            print p["title"].encode("utf-8")
            print "   ",p["url"].encode("utf-8")
            print "   ",p["tags"].encode("utf-8")
            print
        else:
            dAPI.posts_add(p["url"], p["title"], tags=p["tags"], replace="yes")


# Copyright (c) 2009 jetxee@gmail.com
#
# Permission is hereby granted, free of charge, to any person
# obtaining a copy of this software and associated documentation
# files (the "Software"), to deal in the Software without
# restriction, including without limitation the rights to use,
# copy, modify, merge, publish, distribute, sublicense, and/or sell
# copies of the Software, and to permit persons to whom the
# Software is furnished to do so, subject to the following
# conditions:
#
# The above copyright notice and this permission notice shall be
# included in all copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
# OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
# HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
# WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
# OTHER DEALINGS IN THE SOFTWARE.