Skip to content

Instantly share code, notes, and snippets.

What would you like to do?
#!/usr/bin/env ruby
## WP2TUMBLR: WordPress 2 Tumblr Importing tool
## Usage: wp2tumblr [OPTION] WORDPRESS_XML_FILE
## Import the WORDPRESS_XML_FILE to a Tumblr blog.
## Provide `--group` option to publish to a group.
## This could take a long time...
## To install, download the script and chmod to 755.
require 'optparse'
require 'rubygems'
require 'tumblr'
require 'highline/import'
rescue LoadError
abort "Error: #{$!}. Make sure you `gem install tumblr-rb`"
email = nil
password = nil
group = nil
ARGV.options do |option|
option.banner = "Usage: wp2tumblr [options] [file]"
option.separator ""
option.separator "Options"
auth_text = 'Email Address and Password, separated by a colon'
option.on('-a EMAIL:PASSWORD', '--auth EMAIL:PASSWORD', auth_text) do |auth|
email,password = auth.split(':')
option.on('--group=GROUP', 'Publish to a group blog') do |value|
group = value
option.separator ""
if ARGV.empty? && STDIN.tty?
puts ARGV.options
if STDIN.tty?
email = ask("Email Address: ") if !email
password = ask("Password: ") { |q| q.echo = false } if !password
abort 'You need to provide an e-mail address.' if email.blank?
abort 'You need to provide a password.' if password.blank?
puts 'Authenticating to Tumblr...', password).authenticate.perform do |response|
if !response.success?
abort %Q(Oh no! Something went wrong. Tumblr said #{response.code}: "#{response.message}")
puts 'Parsing WordPress XML document...'
wp_xml = Crack::XML.parse(
items = wp_xml['rss']['channel']['item']
puts 'Generating Posts...'
posts = items.collect do |item|
post =
post.title = item['title']
post.body = item['content:encoded']
post.slug = item['wp:post_name'] = item['wp:post_date']
post.tags item['category'].uniq if item['category']
post.state = :draft if !item['wp:status'].eql?('publish') = group if group
post.generator = "wp2tumblr"
abort 'No posts found.' if posts.blank?
published_count = 0
requests = posts.collect do |post|
request = post.write(email,password)
request.on_complete do |response|
if response.success?
published_count += 1
puts %Q(Error publishing post: "#{post.title}". Tumblr says #{response.code}: "#{response.message}")
puts "Publishing #{requests.count} posts..."
if requests.count <= 60
# If there are too many requests, throttle appropriately.
# Make yourself a cup of tea.
requests.each {|req| req.perform; sleep 1 }
puts "Successfully published #{published_count} posts to Tumblr."
Copy link

metamn commented Jul 17, 2010

Any hints for this?
The XML is from a hosted WP blog. Another XML from a self-hosted blog was imported successfully ....

Authenticating to Tumblr...
Parsing WordPress XML document...
/usr/lib/ruby/1.8/rexml/parsers/baseparser.rb:389:in pull': Undefined prefix atom found (REXML::UndefinedNamespaceException) from /usr/lib/ruby/1.8/set.rb:194:ineach'
from /usr/lib/ruby/1.8/set.rb:194:in each_key' from /usr/lib/ruby/1.8/set.rb:194:ineach'
from /usr/lib/ruby/1.8/rexml/parsers/baseparser.rb:387:in pull' from /usr/lib/ruby/gems/1.8/gems/crack-0.1.8/lib/crack/xml.rb:194:inparse'
from wp2tumblr.rb:66

Copy link

mwunsch commented Jul 19, 2010

No ideas. These errors are thrown from rexml: The default XML parser as used by crack. My best guess would be that the hosted blog xml-feed is invalid somehow and REXML is balking. Experiment with replacing lines 66-67 with a different XML parser, such as hpricot or nokogiri. They might be less restrictive.

Copy link

melz commented Nov 21, 2010

I just had the same error message as rubycs mentioned. Remove this line from the XML file and it should work:
<atom:link rel="next" href="http://blabla" />

Copy link

judsond commented Mar 19, 2011

I got that error also, and removing that line also fixed it.

I'm getting something new though:

./wp2tumblr:76: undefined method 'uniq' for "meta":String (NoMethodError)
from ./wp2tumblr:70:in 'collect'
from ./wp2tumblr:70`

Any ideas?

Copy link

judsond commented Mar 19, 2011

Maybe something like:

post.tags item['category'].uniq if item['category'].class == Array
post.tags item['category'].split if item['category'].class == String

Please improve that as you want, I'm very amateur :) This seems to work though, and removes the error.

Copy link

gyaresu commented Apr 14, 2011

@judsond Worked here for self hosted Wordpress import.


Copy link

allirense commented Jul 30, 2012

Does this still work? I'm getting this when I try to run the script:

/Library/Ruby/Gems/1.8/gems/tumblr-rb-1.3.0/lib/tumblr/post.rb:13:in parameters': undefined methodblank?' for [:title, :body]:Array (NoMethodError)
from /Library/Ruby/Gems/1.8/gems/tumblr-rb-1.3.0/lib/tumblr/post/regular.rb:10
from /System/Library/Frameworks/Ruby.framework/Versions/1.8/usr/lib/ruby/1.8/rubygems/custom_require.rb:31:in gem_original_require' from /System/Library/Frameworks/Ruby.framework/Versions/1.8/usr/lib/ruby/1.8/rubygems/custom_require.rb:31:inrequire'
from /Library/Ruby/Gems/1.8/gems/tumblr-rb-1.3.0/lib/tumblr/post.rb:184
from /System/Library/Frameworks/Ruby.framework/Versions/1.8/usr/lib/ruby/1.8/rubygems/custom_require.rb:31:in gem_original_require' from /System/Library/Frameworks/Ruby.framework/Versions/1.8/usr/lib/ruby/1.8/rubygems/custom_require.rb:31:inrequire'
from /Library/Ruby/Gems/1.8/gems/tumblr-rb-1.3.0/lib/tumblr.rb:8
from /System/Library/Frameworks/Ruby.framework/Versions/1.8/usr/lib/ruby/1.8/rubygems/custom_require.rb:36:in gem_original_require' from /System/Library/Frameworks/Ruby.framework/Versions/1.8/usr/lib/ruby/1.8/rubygems/custom_require.rb:36:inrequire'
from ./wp2tumblr:16

Copy link

nz commented Dec 28, 2012

Looks like this gist may be out of date with its dependencies. @mwunsch, any chance of an update?

Copy link

allisonburtch commented Mar 23, 2013

I'd love an update as well. Thanks! @mwunsch

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