]> git.vanrenterghem.biz Git - git.ikiwiki.info.git/blob - doc/tips/importing_posts_from_wordpress/ikiwiki-wordpress-import.mdwn
(no commit message)
[git.ikiwiki.info.git] / doc / tips / importing_posts_from_wordpress / ikiwiki-wordpress-import.mdwn
1 [[!meta title="ikiwiki-wordpress-import"]]
3 I modified the script a bit so categories and tags would actually show up in the output file.
5 -----
6 <pre>
7 #!/usr/bin/env python
9 """
10     Purpose:
11     Wordpress-to-Ikiwiki import tool
13     Copyright:
14     Copyright (C) 2007  Chris Lamb <chris@chris-lamb.co.uk>
16     This program is free software: you can redistribute it and/or modify
17     it under the terms of the GNU General Public License as published by
18     the Free Software Foundation, either version 3 of the License, or
19     (at your option) any later version.
21     This program is distributed in the hope that it will be useful,
22     but WITHOUT ANY WARRANTY; without even the implied warranty of
23     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
24     GNU General Public License for more details.
26     You should have received a copy of the GNU General Public License
27     along with this program.  If not, see <http://www.gnu.org/licenses/>.
29     Usage: run --help as an argument with this script.
31     Notes:
32     I added some extra bits to include the \[[!tag foo]] stuff in the post,
33     as it wasn't before, at all. I'll diff the versions out so you can see
34     the mess I made :).
36 """
38 import os, sys
39 import time
40 import re
42 from BeautifulSoup import BeautifulSoup
44 import codecs, htmlentitydefs
46 codecs.register_error('html_replace', lambda x: (''.join([u'&%s;' \
47     % htmlentitydefs.codepoint2name[ord(c)] for c in x.object[x.start:x.end]]), x.end))
49 def main(name, email, subdir, branch='master'):
50     soup = BeautifulSoup(sys.stdin.read())
52     # Regular expression to match stub in URL.
53     stub_pattern = re.compile(r'.*\/(.+)\/$')
55     for x in soup.findAll('item'):
56         # Ignore draft posts
57         if x.find('wp:status').string != 'publish': continue
59         match = stub_pattern.match(x.guid.string)
60         if match:
61             stub = match.groups()[0]
62         else:
63             # Fall back to our own stubs
64             stub = re.sub(r'[^a-zA-Z0-9_]', '-', x.title.string).lower()
66         commit_msg = """Importing WordPress post "%s" [%s]""" % (x.title.string, x.guid.string)
67         timestamp = time.mktime(time.strptime(x.find('wp:post_date_gmt').string, "%Y-%m-%d %H:%M:%S"))
69         content = '\[[!meta title="%s"]]\n\n' % (x.title.string.replace('"', r'\"'))
70         content += x.find('content:encoded').string.replace('\r\n', '\n')
72         # categories = x.findAll('category')
73         # categories = x.findAll({'category':True}, attrs={'domain':re.compile(('category|tag'))})
74         # categories = x.findAll({'category':True}, domain=["category", "tag"])
75         # categories = x.findAll({'category':True}, nicename=True)
76         """
77         We do it differently here because we have duplicates otherwise.
78         Take a look:
79         &lt;category&gt;&lt;![CDATA[Health]]&gt;&lt;/category&gt;
80         &lt;category domain="category" nicename="health"&gt;&lt;![CDATA[Health]]&gt;&lt;/category&gt;
82         If we do the what original did, we end up with all tags and cats doubled.
83         Therefore we only pick out nicename="foo". Our 'True' below is our 'foo'.
84         I'd much rather have the value of 'nicename', and tried, but my
85         python skillz are extremely limited....
86         """
87         categories = x.findAll('category', nicename=True)
88         if categories:
89             content += "\n"
90             for cat in categories:
91                 # remove 'tags/' because we have a 'tagbase' set.
92                 # your choice: 'tag', or 'taglink'
93                 # content += "\n\[[!tag %s]]" % (cat.string.replace(' ', '-'))
94                 content += "\n\[[!taglink %s]]" % (cat.string.replace(' ', '-'))
95                 # print >>sys.stderr, cat.string.replace(' ', '-')
97         # moved this thing down
98         data = content.encode('ascii', 'html_replace')
99         print "commit refs/heads/%s" % branch
100         print "committer %s &lt;%s&gt; %d +0000" % (name, email, timestamp)
101         print "data %d" % len(commit_msg)
102         print commit_msg
103         print "M 644 inline %s" % os.path.join(subdir, "%s.mdwn" % stub)
104         print "data %d" % len(data)
105         print data
107 if __name__ == "__main__":
108     if len(sys.argv) not in (4, 5):
109         print >>sys.stderr, "%s: usage: %s name email subdir [branch] < wordpress-export.xml | git-fast-import " % (sys.argv[0], sys.argv[0])
110     else:
111         main(*sys.argv[1:])
113 </pre>
114 -----
116 I have another version of the script, which uses the `timestamp` from the script, and inserts that as a \[[!meta date="foodate"]]. I'm posting it here just in case I happen to be doing something to the httpd.
118 (Hopefully I've escaped everything properly; if I missed something, check the source.)
120 -----
121 <pre>
122 #!/usr/bin/env python
124 """
125     Purpose:
126     Wordpress-to-Ikiwiki import tool
128     Copyright:
129     Copyright (C) 2007  Chris Lamb <chris@chris-lamb.co.uk>
131     This program is free software: you can redistribute it and/or modify
132     it under the terms of the GNU General Public License as published by
133     the Free Software Foundation, either version 3 of the License, or
134     (at your option) any later version.
136     This program is distributed in the hope that it will be useful,
137     but WITHOUT ANY WARRANTY; without even the implied warranty of
138     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
139     GNU General Public License for more details.
141     You should have received a copy of the GNU General Public License
142     along with this program.  If not, see <http://www.gnu.org/licenses/>.
144     Usage: run --help as an argument with this script.
146     Notes:
147     I added some extra bits to include the \[[!tag foo]] stuff in the post,
148     as it wasn't before, at all. I'll diff the versions out so you can see
149     the mess I made :).
151 """
153 import os, sys
154 import time
155 import re
157 from datetime import datetime
158 from BeautifulSoup import BeautifulSoup
160 import codecs, htmlentitydefs
162 codecs.register_error('html_replace', lambda x: (''.join([u'&%s;' \
163     % htmlentitydefs.codepoint2name[ord(c)] for c in x.object[x.start:x.end]]), x.end))
165 def main(name, email, subdir, branch='master'):
166     soup = BeautifulSoup(sys.stdin.read())
168     # Regular expression to match stub in URL.
169     stub_pattern = re.compile(r'.*\/(.+)\/$')
171     for x in soup.findAll('item'):
172         # Ignore draft posts
173         if x.find('wp:status').string != 'publish': continue
175         match = stub_pattern.match(x.guid.string)
176         if match:
177             stub = match.groups()[0]
178         else:
179             # Fall back to our own stubs
180             stub = re.sub(r'[^a-zA-Z0-9_]', '-', x.title.string).lower()
182         commit_msg = """Importing WordPress post "%s" [%s]""" % (x.title.string, x.guid.string)
183         timestamp = time.mktime(time.strptime(x.find('wp:post_date_gmt').string, "%Y-%m-%d %H:%M:%S"))
184         content = '\[[!meta title="%s"]]\n' % (x.title.string.replace('"', r'\"'))
185         content += "\[[!meta date=\"%s\"]]\n" % datetime.fromtimestamp(timestamp)
186         content += x.find('content:encoded').string.replace('\r\n', '\n')
188         """
189         We do it differently here because we have duplicates otherwise.
190         Take a look:
191         &lt;category&gt;&lt;![CDATA[Health]]&gt;&lt;/category&gt;
192         &lt;category domain="category" nicename="health"&gt;&lt;![CDATA[Health]]&gt;&lt;/category&gt;
194         If we do the what original did, we end up with all tags and cats doubled.
195         Therefore we only pick out nicename="foo". Our 'True' below is our 'foo'.
196         I'd much rather have the value of 'nicename', and tried, but my
197         python skillz are extremely limited....
198         """
199         categories = x.findAll('category', nicename=True)
200         if categories:
201             content += "\n"
202             for cat in categories:
203                 # remove 'tags/' because we have a 'tagbase' set.
204                 # your choice: 'tag', or 'taglink'
205                 # content += "\n\[[!tag %s]]" % (cat.string.replace(' ', '-'))
206                 content += "\n\[[!taglink %s]]" % (cat.string.replace(' ', '-'))
207                 # this is just debugging, and for fun
208                 # print >>sys.stderr, cat.string.replace(' ', '-')
210         # moved this thing down
211         data = content.encode('ascii', 'html_replace')
212         print "commit refs/heads/%s" % branch
213         print "committer %s &lt;%s&gt; %d +0000" % (name, email, timestamp)
214         print "data %d" % len(commit_msg)
215         print commit_msg
216         print "M 644 inline %s" % os.path.join(subdir, "%s.mdwn" % stub)
217         print "data %d" % len(data)
218         print data
220 if __name__ == "__main__":
221     if len(sys.argv) not in (4, 5):
222         print >>sys.stderr, "%s: usage: %s name email subdir [branch] < wordpress-export.xml | git-fast-import " % (sys.argv[0], sys.argv[0])
223     else:
224         main(*sys.argv[1:])
226 </pre>
227 -----
230 [[!tag wordpress]]
231 [[!tag python]]
232 [[!tag conversion]]
233 [[!tag ikiwiki]]