2020-06
18

BlogBus 2 WordPress – by xrspook

By xrspook @ 19:50:07 归类于: 扮IT

为什么要学习python?因为我见识过python有多牛逼,简单一个脚本文件,轻量级的东西实现强大的功能。因为要做XML文件的格式转换,所以我觉得我要学好python。Think Python 2看到第14章,我就转向去研究10年多以前网友写的BlogBus转WordPress的python脚本。之所以要研究,因为当时的WordPress格式和现在不一样,用以前的脚本转换出来的东西已经没办法直接导入到现在的WordPress里了。再去找写代码的那些人,有些网站还在,但有些已经消失了。我不能等待别人拯救我,我只能自己拯救自己。

我需要转换格式的是“回到过去——Betty迷的独白”和“Mi Internacional Cielo”,这两个旧BlogBus站点和我的主站“我的天”不一样,虽然里面有不少我原创的东西,但我从四面八方搜集回来的内容也不少。当时的BlogBus默认编辑界面是富文本,我看上去觉得格式没问题大概就可以了,但实际上格式是有问题的。从五湖四海搜集回来的文字里面怎么可能不夹杂各种格式,那些东西在富文本编辑下可能看不出来,但在源代码界面一团糟。如果当年我复制粘贴的时候有先去记事本过渡一下就不会有那么多的问题。所以除了要转换BlogBus和WordPress的标签以外我还要筛选删除那些坏事的源代码。

经过接近一周的努力,我终于整出来了。运行下面的python3脚本,如果能顺利完成,自动生成出新的XML文件,用官方途径导入WordPress 5.4.2是完全没有问题的,但我只测试了我自己的两个blog,是不是兼容其它我不知道。因为转换blog我是有自己的想法的,所以脚本中有一些个性化的东西,比如我把blog的标题变成了分类,把原来的分类变成了标签。脚本中有大量的反转义替换,主要是为了人去看CDATA的时候不太头晕迷糊,因为我那两个旧blog里有大量的西班牙语字符,不同的编码下,BlogBus的导出文件里有些被转义了有些没有。那些转义了的放到WordPress里不知道WordPress会不会转回来,我试过标题被BlogBus转义之后WordPress不会转回来,看得我云里雾里。因为转义很头痛,所以除了少数几个内容,有可能被转义的文字都被我用CDATA包裹了起来。

脚本不是我一个人的功劳,我只是在当年网友脚本的基础上做了调整,使之适配python3和WordPress 5.4.2。

我的脚本:xbus2wp.py (PS:下面脚本330行的《/p》是什么鬼怪!WordPress的脚本插件在搞什么!)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
'''
***使用说明***
终端界面输入xbus2wp.py bus.xml xrspook。其中:
xbus2wp.py为脚本名字,bus.xml为BlogBus导出文件,xrspook为博主名字,3个参数以空格分开
若运行无误,输出的文件名为[原文件名_xbus2wp.xml]
脚本基于python3,适配WordPress 5.4.2(2020-06-18)
'''
 
import re, sys, getopt, datetime
from xml.dom import minidom
from time import time
 
def convert(inputFileName, owner, order='asc'):
    """"""
    try:
        xmldoc = minidom.parse(inputFileName)
    except Exception as e:
        print ('Fail.')
        print (e)
        print ('Please repair or delete invalid token like "& < >" there.')
        sys.exit(1)
 
    bus = xmldoc.documentElement
    logs = bus.getElementsByTagName('Log')
 
    dom = minidom.Document()
    rss = dom.createElement('rss') # rss是root,根元素
    dom.appendChild(rss)      
    rss.setAttribute('version', '2.0')
    rss.setAttribute('xmlns:content', 'http://purl.org/rss/1.0/modules/content/')
    rss.setAttribute('xmlns:wfw', 'http://wellformedweb.org/CommentAPI/')
    rss.setAttribute('xmlns:dc', 'http://purl.org/dc/elements/1.1/')
    rss.setAttribute('xmlns:wp', 'http://wordpress.org/export/1.0/')
    channel = dom.createElement('channel')
    rss.appendChild(channel)
    wxr_version = dom.createElement('wp:wxr_version') # 加入wxr戳,无戳无法进行WordPress导入
    channel.appendChild(wxr_version)
    wxr_version_node = dom.createTextNode('1.1')
    wxr_version.appendChild(wxr_version_node)
 
    busname = bus.getElementsByTagName('BlogName')[0] # 提取原BlogBus名字
    busname_text = getElementData(busname).replace(' ', '_')
 
    # create a list to contain items instead of appending them to
    # channel directly in order to sort them of lately according to order.
    if order == 'desc':
        item_list = []
    else:
        item_list = None
 
    for log in logs:
        title = log.getElementsByTagName('Title')[0]
        title_text = getElementData(title)
        content = log.getElementsByTagName('Content')[0]
        content_text = getElementData(content)
        logdate = log.getElementsByTagName('LogDate')[0]
        pubdate = getElementData(logdate)
        writer = log.getElementsByTagName('Writer')[0]
        creator = owner # BlogBus的writer根本没包含元素!
        category = getElementData(log.getElementsByTagName('Sort')[0])
        tagi = log.getElementsByTagName('Tags')[0]
        tags = getElementData(tagi).split(' ')
        new_tags = unique_tag(category, tags) # 新的wp标签里包含了原BlogBus里的分类与标签
        comments = log.getElementsByTagName('Comment')
 
        #-----
        item = dom.createElement('item')
 
        # handle title
        title_element = createElement(dom, 'title', title_text, 'cdata')
        item.appendChild(title_element)
 
        # handle type
        type_element = createElement(dom, 'wp:post_type', 'post', 'cdata')
        item.appendChild(type_element)
 
        # handle pubdate
        pubdate_element = createElement(dom, 'pubDate', convertPubDate(pubdate))
        item.appendChild(pubdate_element)
 
        # handle creator
        creator_element = createElement(dom, 'dc:creator', creator, 'cdata')
        item.appendChild(creator_element)
 
        # handle categories with domain
        category_element = createElement(dom, 'category', busname_text, 'cdata') # 把BlogBus标题设置为分类,因为我要合并多个旧blog
        category_element.setAttribute('domain','category')
        category_element.setAttribute('nicename', busname_text)
        item.appendChild(category_element)
 
        # handle tags
        for tag in new_tags:
            tag = tag.replace('&ntilde;', 'n')
            tag = tag.replace('summary_of_BLF', 'summary_of_BLF(from_rincondebetty)')
            tag = tag.replace('summary_of_EcoModa', 'summary_of_EcoModa(from_rincondebetty)')
            category_element = createElement(dom, 'category', tag, 'cdata')
            category_element.setAttribute('domain','post_tag')
            category_element.setAttribute('nicename', tag)
            item.appendChild(category_element)
 
        # handle content
        content_element = createElement(dom, "content:encoded", content_text, 'cdata')        
        item.appendChild(content_element)
 
        # handle post_date
        post_date_element = createElement(dom, "wp:post_date", pubdate)
        item.appendChild(post_date_element)
 
        # handle status
        status_element = createElement(dom, "wp:status", 'publish')
        item.appendChild(status_element)
 
        # handle comments
        if comments:
            commentElements = createComments(dom, comments)
            for commentElement in commentElements:
                item.appendChild(commentElement)
 
        if item_list != None:
            item_list.append(item)
        else:
            channel.appendChild(item)
 
    if item_list:
        item_list.reverse()
        for m in item_list:
            channel.appendChild(m)
 
    global filename # 输出设置
    output = filename + '_xbus2wp.xml'
    f = open(output ,'wb+')
    import codecs
    writer = codecs.lookup('utf-8')[3](f)
    dom.writexml(writer, '', ' ' * 4, '\n', encoding='utf-8')
    writer.close()
 
def unique_tag(category,tags): # 只保留唯一的标签
    category = category.replace(' ', '_')
    l = category.split() + tags
    new_l = []
    for item in l:
        if item not in new_l and item != '(from_rincondebetty)':
            new_l.append(item.replace(' ', '_')) # 替换空格为下划线
    return new_l
 
def getElementData(element): # 获取节点数据
    """"""
    data = ''
    for node in element.childNodes:
        if node.nodeType in (node.TEXT_NODE, node.CDATA_SECTION_NODE):
            data += node.data
    return data
 
def createComments(dom, comments):
    """"""
    l = []
    count = 0
    for comment in comments:
        count += 1 # 每篇文章的评论序号,没有序号,评论只能导入每篇最后一条
        email = comment.getElementsByTagName('Email')[0]
        homepage = comment.getElementsByTagName('HomePage')[0]
        name = comment.getElementsByTagName('NiceName')[0]
        content = comment.getElementsByTagName('CommentText')[0]
        date = comment.getElementsByTagName('CreateTime')[0]
        comment_element = createCommentElement(count, dom, email, homepage, name, content, date)
        l.append(comment_element)
    return l
 
def createCommentElement(count, dom, email, homepage, name, content, date):
    """"""
    comment_author = getElementData(name)
    comment_author_email = getElementData(email)
    comment_author_url = getElementData(homepage)
    comment_date = getElementData(date)
    comment_content = getElementData(content)
 
    comment_id_element = createElement(dom, 'wp:comment_id', str(count))
    comment_author_element = createElement(dom, 'wp:comment_author', comment_author)
    comment_author_email_element = createElement(dom, 'wp:comment_author_email', comment_author_email)
    comment_author_url_element = createElement(dom, 'wp:comment_author_url', comment_author_url)
    comment_date_element = createElement(dom, 'wp:comment_date', comment_date)
    comment_date_gmt_element = createElement(dom, 'wp:comment_date_gmt', comment_date)
    comment_content_element = createElement(dom, 'wp:comment_content', comment_content, 'cdata')
    comment_approved_element = createElement(dom, 'wp:comment_approved', '1')
 
    # make the comment element
    comment_element = dom.createElement('wp:comment')
    comment_element.appendChild(comment_id_element)
    comment_element.appendChild(comment_author_element)
 
    # validate email and url
    validEmail = validateEmail(comment_author_email)
    if (validEmail):
        comment_element.appendChild(comment_author_email_element)
 
    validUrl = validateUrl(comment_author_url)
    if (validUrl):
        comment_element.appendChild(comment_author_url_element)    
 
    comment_element.appendChild(comment_date_element)
    comment_element.appendChild(comment_date_gmt_element)
    comment_element.appendChild(comment_content_element)
    comment_element.appendChild(comment_approved_element)
 
    return comment_element
 
def createElement(dom, elementName, elementValue, type='text'): #建立节点标签和节点
    """"""
    global owner
    tag = dom.createElement(elementName)
    if elementValue.find(']]>') > -1:
        type = 'text'
    if type == 'text':
        text = dom.createTextNode(elementValue)
    elif type == 'cdata':
        elementValue = elementValue.replace('&amp;', '&')
        elementValue = elementValue.replace('&lt;', '<')
        elementValue = elementValue.replace('&gt;', '>')
        elementValue = elementValue.replace('&apos;', '\'')
        elementValue = elementValue.replace('&quot;', '"')
 
        # 大量替换与我的旧blog有各种编码的西班牙语字符有关
        elementValue = elementValue.replace('&copy;', '') # 版权标志
        elementValue = elementValue.replace('&nbsp;', '') # 空格
        elementValue = elementValue.replace('&ldquo;', '“') # 左双引号
        elementValue = elementValue.replace('&rdquo;', '”') # 右双引号
        elementValue = elementValue.replace('&lsquo;', '‘') # 左单引号
        elementValue = elementValue.replace('&rsquo;', '’') # 右单引号
        elementValue = elementValue.replace('&acute;', '´') # 单引号
        elementValue = elementValue.replace('&hellip;', '...') # 省略号
        elementValue = elementValue.replace('&mdash;', '—') # 破折号
        elementValue = elementValue.replace('&middot;', '·') # 分隔号
        elementValue = elementValue.replace('&deg;', '°') # 单位度
        elementValue = elementValue.replace('&iexcl;', '¡') # 西班牙语反叹号
        elementValue = elementValue.replace('&iquest;', '¿') # 西班牙语反问号
        elementValue = elementValue.replace('&ntilde;', 'ñ') # 西班牙语n
        elementValue = elementValue.replace('&Ntilde;', 'Ñ') # 西班牙语N
        elementValue = elementValue.replace('&aacute;', 'á') # 西班牙语a
        elementValue = elementValue.replace('&eacute;', 'é') # 西班牙语e
        elementValue = elementValue.replace('&iacute;', 'í') # 西班牙语i
        elementValue = elementValue.replace('&oacute;', 'ó') # 西班牙语o
        elementValue = elementValue.replace('&uacute;', 'ú') # 西班牙语u
        elementValue = elementValue.replace('&Aacute;', 'Á') # 西班牙语A
        elementValue = elementValue.replace('&Eacute;', 'É') # 西班牙语E
        elementValue = elementValue.replace('&Iacute;', 'Í') # 西班牙语I
        elementValue = elementValue.replace('&Oacute;', 'Ó') # 西班牙语O
        elementValue = elementValue.replace('&Uacute;', 'Ú') # 西班牙语U
        elementValue = elementValue.replace('&Atilde;', 'Ã') # 西班牙语A~
        elementValue = elementValue.replace('&ordf;', 'ª') # 西班牙语上标a
        elementValue = elementValue.replace('&ordm;', 'º') # 西班牙语上标o
 
        elementValue = elementValue.replace('<!--msnavigation-->', '')
        elementValue = elementValue.replace('博主', owner)
        elementValue = elementValue.replace('<i>', '')
        elementValue = elementValue.replace('</i>', '')
        elementValue = elementValue.replace('<br /><br />', '<br />')
 
        elementValue = re.sub(r"(?:<\?xml.*?>)", "", elementValue)
        elementValue = re.sub(r"(?:<[TDSFHI].*?>)", "", elementValue)
        elementValue = re.sub(r"(?:<\/[TDSFHI].*?>)", "", elementValue)
        elementValue = re.sub(r"(?:<P.*?>)", "<p>", elementValue)
        elementValue = re.sub(r"(?:<(table|tbody|tr|td|div|span|img|script|font|hr|object|param).*?>)", "", elementValue)
        elementValue = re.sub(r"(?:<\/(table|tbody|tr|td|div|span|img|script|font|object).*?>)", "", elementValue)
        elementValue = re.sub(r"\n", "", elementValue) # 把替换造成的空行删除
 
        text = dom.createCDATASection(elementValue)
    tag.appendChild(text)
    return tag
 
def convertPubDate(date, timediff='+0000'):
    """
    convert 2003-08-22 16:01:56
    to Thu, 23 Aug 2007 05:47:54 +0000
    """
    year, mon, day = int(date[:4]), int(date[5:7]), int(date[8:10])
    time = date[11:]
    aday = datetime.datetime(year, mon, day)
    d = {'1':'Mon', '2':'Tus', '3':'Wen', '4':'Thur', '5':'Fri', '6':'Sat', '7':'Sun'}
    m = {'1':'Jan', '2':'Feb', '3':'Mar', '4':'Apr', '5':'May', '6':'Jun',
         '7':'Jul', '8':'Aug', '9':'Sep', '10':'Oct', '11':'Nov', '12':'Dec'}
    weekday = d[str(aday.isoweekday())]
    month = m[str(mon)]
    pubdate = "%s, %d %s %s %s %s" % (weekday, day, month, year, time, timediff)
    return pubdate
 
def validateEmail(email):
    '''
    '''
    pattern = r'^[0-9a-z][_.0-9a-z-]{0,31}@([0-9a-z][0-9a-z-]{0,30}[0-9a-z]\.){1,4}[a-z]{2,4}$'
    p = re.compile(pattern)
    m = p.match(email)
    if m:
        return True
    else:
        return False
 
def validateUrl(url):
    '''
    '''
    pattern = r'^[a-zA-z]+://(\w+(-\w+)*)(\.(\w+(-\w+)*))*(\?\S*)?$'
    p = re.compile(pattern)
    m = p.match(url)
    if m:
        return True
    else:
        return False
 
def main(argv=None):    
    global filename
    global owner
 
    if argv is None:
        argv = sys.argv
    # parse command line options
 
    args = sys.argv[1:]
    order='asc'
    if (len(args) == 2):
        print ('Converting...'),
        sys.stdout.flush()
        start = time()
        filename = args[0].replace('.xml', '')
        owner = args[1] # BlogBus没把博主名字输出,只能手动
        convert(args[0], args[1], order)
        end = time()
        print ('Done. Elapse %g seconds.' % (end - start))
 
if __name__ == "__main__":
    sys.exit(main())
</p>
2020-06
18

拉黑

By xrspook @ 9:17:02 归类于: 烂日记

什么人会被我拉黑呢?那通常是我的同事。什么同事会被我拉黑呢?通常是那种不在上班时间找我,而下班时间一个电话过来让你干嘛干嘛的人。完全不会考虑当时你真在做什么,反正他们觉得24小时你都应该回答他们的问题,为他们工作,随时让你加班,那是再正常不过的事。我非常讨厌这种人,无论那是我的领导,还是我的同事,又或者是下属。当然最后这个选项是不存在的,因为我很讨厌之前两种人这么干,所以到现在为止,我也不会对我下面的人有这样的要求。即便我在工作时间以外找下属,都不是因为工作。上班的时候不找你,下班的时候才跟你说很急很忙,这到底是什么意思呢!这意味着他们永远把与你相关的工作的优先级设定为最低,所以在上班的时候、精力旺盛的时候根本不觉得你有存在感。当他们迷迷糊糊,又或者被某些人逼迫着要交某些东西的时候,就突然想起原来还有一个之前被他们丢一边的问题没有解决。曾经我试过莫名其妙没有任何先兆,下班了以后一个电话就叫你回去加班。有些时候我能预知到这种结果,我也知道我是唯一的选项,所以我试过直接不理睬他们的电话,人也不让他们找到。他们明明可以在下班之前就告知我,下班之后有加班这种事,但他们却没有这么干。

我很讨厌加班,虽然我经常莫名其妙加很多班,但是这种加班我从来没有要过单位一分钱加班费,因为那是我心血来潮,想要做某些东西。当我的兴趣上去了以后,根本停不下来,当我正在潜心做某件事的时候,根本没有上班与下班之分。我是这样的人,但我不能逼迫我的同事和我的下属也跟我一样。所以即便加了很多的斑,但是那种加班都只对我一个人有影响,这些加班完全不需要其他人加入其中。所以一整个晚上或者一整个周末的时间没了都只是我一个人的事。领导知不知道无所谓,同事知不知道也无所谓,我也没想过他们给我加班费。之所以那样干是因为我喜欢。但是,别人硬逼要我加班的那种,我很讨厌。因为我极度讨厌那种事,当某些人一次又一次强迫我做那种事的时候,我就会把他拉黑,无论他是谁。

当我去找别人帮忙的时候,我会很在意找别人的时机。除非那是我非常熟的人。最熟悉的朋友,任何时点去找他们都不是问题。因为或许他们不会马上恢复你,但是他们仍然会把那件事记在心里,他们总会帮你做的,如果他们力所能及,这就是信任。但是那些纯粹只是普通得不能再普通的同事关系的人,你怎么好意思完全不考虑时间去骚扰别人呢!到现在为止,我仍只是个小不点,我不是领导,所以我不是那种,7天24小时随时接受任务的人。当他们逼迫我得这么干的时候,我会直接不鸟。在这方面,我是个非常我行我素的人。毕竟过去10年有余的工作经历告诉我,即便我在下班的时间帮了那些人,他们也不会给我什么好处。反过来,下班之后我完全不理睬他们,他们也没办法拿我怎样。

将心比心是必须的。如果你自己是没有被虐底线的,起码在虐别人的时候,得考虑一下,对方是不是也跟你一样。

© 2004 - 2020 我的天 | Theme by xrspook | Power by WordPress