部落格大搬家
半夜無眠
由於不久前才在Github上架設了這個blog,如果不把之前在痞客邦寫的文章搬遷過來,感覺會有點空虛。
其實要備份痞客邦的文章非常方便,只要在後台管理介面的設定管理
內的匯入/匯出
就可以輸出.txt
檔案。
有趣的問題來了,輸出的檔案格式似乎跟markdown不太相同,要一篇一篇手動修改,對目前只有30幾篇文章,我的渣部落格而言應該很快就能搞定,但是對於比較大規模的部落格能有較系統化的處理方式嗎?
想嘗試用Python處理文檔,由備份文件自動產生post的想法就一直在腦海中揮之不去,輾轉難眠之下我決定開一個Github repository專門來處理各種blog的疑難雜症。
程式規劃
之前在學習Python的時候,發現了這一本書完全免費公開在網路上,而其中的第8章節就有講述到檔案的讀寫。
只要有這些基礎知識,應該不難將痞客邦匯出的.txt
軟為符合Jekyll格式的.md
文檔。
然而在動手開始寫程式前,有一個完整的規劃,是寫好程式的第一步。
- 拆解文章: 由於匯出的文件總結了全部的文章,並且還包含了comments以及有的沒的分隔字串。所以將每篇文章,拆成對應的一份份
.md
檔是首要動作。 - 修正格式: 對於每個
.md
文檔,對metadata及內文都要整理成符合Jeykyll的markdown格式。
路徑設定
# 設定匯出檔案的位置,我是放在/pixnet_backup/blog-export-mt-KWbuster-20170714081020.txt
file_path = os.path.join(os.path.dirname(__file__), 'pixnet_backup', 'blog-export-mt-KWbuster-20170714081020.txt')
# 設定輸出.md檔案的資料夾
post_dir = os.path.join(os.path.dirname(__file__), 'posts')
# 產生存放.md文檔的資料夾
if not os.path.exists(post_dir):
os.makedirs(post_dir)
拆解文章
第一步是找到分割每篇post的字串,觀察過後小弟自以為的決定TITLE
應該是個關鍵的字串,如此一來就可以分割並產生一份份的.md
文檔。
# 讀取.txt檔案,依照分行存成list
with open(file_path, 'rb') as read_file:
file_list = read_file.readlines()
# 依照文件中的"TITLE"來區分出每一篇post
init_ind, end_ind = 0, 0
while init_ind < len(file_list) and end_ind < len(file_list):
# 藉由"TITLE"字串分割post
if (end_ind != 0) and ('TITLE'.encode('utf-8') in file_list[end_ind]):
file_content, file_name = generate_post(init_ind, end_ind, file_list)
# 將file_content寫入markdown文檔
if 'publish'.encode('utf-8') in file_content[5]:
print('process... %s' %file_name)
with open(post_dir + '/' + file_name, 'wb') as write_file:
write_file.writelines(file_content)
init_ind = end_ind
end_ind += 1
# last post
file_content, file_name = generate_post(init_ind, end_ind, file_list)
if 'publish'.encode('utf-8') in file_content[5]:
print('process... %s' %file_name)
with open(post_dir + '/' + file_name, 'wb') as write_file:
write_file.writelines(file_content)
這部分會用到一個小小的副程式,用意在於由.txt
內的文件得到每篇文章.md
檔名應該要有的檔案格式,範例如下:
def generate_post(init_ind, end_ind, file_list):
file_content = file_list[init_ind:end_ind - 1]
title = file_list[init_ind].decode("utf-8")[7:-1]
date = file_list[init_ind+2].decode("utf-8")[6:16]
file_name = '%s-%s-%s-%s.md' %(date[-4:], date[:2], date[-7:-5], title[:-1]) # title[:-1]是當結尾是'\r'時的解法
return file_content, file_name
修正格式
目前拆解出來的.md
文件慢慢開始有點感覺囉,接下來就是分別對metadata、content部分進行格式修改。
# 逐一讀取前一個步驟產生的.md文檔
post_files = [x[2] for x in os.walk(post_dir)][0]
for post_file in post_files:
with open(post_dir + '/' +post_file, 'rb') as read_file:
post_content = read_file.readlines()
print('Markdown...%s' %post_file)
# 將文檔分為metadata與content部分
for ind in range(len(post_content)):
if 'BODY'.encode('utf-8') in post_content[ind]:
metadata = post_content[:ind]
content = post_content[ind+1:-1]
# 分別以下列兩個副程式處理格式
output_metadata = generate_metadata(metadata)
output_content = generate_content(content)
with open(post_dir + '/' +post_file, 'wb') as write_file:
write_file.writelines(output_metadata+output_content)
處理格式用的副程式如下,可能還需要微調。
def generate_metadata(metadata):
output_metadata = []
output_metadata.append(b'---\n')
output_metadata.append(b'layout: single\n')
for line in metadata:
# 設定標題
if 'TITLE'.encode('utf-8') in line:
output_metadata.append(b'title: %s' %line[7:])
# 設定發文時間
if 'DATE'.encode('utf-8') in line:
if 'AM'.encode('utf-8') in line:
output_metadata.append(b'date: %s-%s-%s %s:%s:%s\n' %(line[12:16], line[6:8], line[9:11], line[17:19], line[20:22], line[23:25]))
else:
hour = int(line[17:19])
if hour < 12:
time = str(hour+12).encode('utf-8')
else:
time = str(hour).encode('utf-8')
output_metadata.append(b'date: %s-%s-%s %s:%s:%s\n' %(line[12:16], line[6:8], line[9:11], time, line[20:22], line[23:25]))
# 設定文章類別
if 'PRIMARY CATEGORY'.encode('utf-8') in line:
output_metadata.append(b'categories:\n')
output_metadata.append(b'- %s\n' %line[18:-2])
# 設定標記
if 'TAGS'.encode('utf-8') in line:
tag_list=str(line[6:-2], 'utf-8').split(',')
output_metadata.append(b'tags:\n')
for tag in tag_list:
output_metadata.append(b'- %s\n' %(tag[1:-1].encode('utf-8')))
output_metadata.append(b'---\n')
output_metadata.append(b'\n')
def generate_content(content):
output_content = []
for line in content:
#空格直接忽略
if ' '.encode('utf-8') in line:
pass
# <p></p>也可以直接無視
elif '<p>'.encode('utf-8') in line:
output_content.append(b'%s\n' %line[3:-6])
# 回覆留言部分直接跳過
elif 'COMMENT'.encode('utf-8') in line:
output_content = output_content[:-1]
break
else:
output_content.append(line)
return output_content
細節修正
經過一個下午的奮戰,終於將所有的post轉換成.md
,但是奮戰還沒結束,我發現竟然舊的blog的標題全部不見了,類別也沒在固定的位置,慘慘慘!
最終問題是post中的title
,應該是不能有特殊的符號斷開,經過測試後終於搞定,詳見Github。
但是還沒結束呢,剩下才是痛苦的地方,因為有大量的照片圖片要搬遷,以及每篇部落格的段落要重新編排,剩餘的主要工作如下:
- 文章目錄
- 文章簡介
- 文章內的連結、欄位格式修正
- 文章內的圖片:痞客邦非常不貼心,沒有圖片備份的功能,參考相關網站的介紹後,下載了WGet(目前2017-05-24還有更新)對相簿圖片進行備份,但是文章使用圖片還是得人工修改。
時間真的夠嗎?
- [2017-08-31] 網路上找了老半天如何設定痞客邦文章頁面的跳轉,結果中文網站盡是一堆…ㄌㄐ。 但是在StackOverflow大神的引領下,終於整理出下方跳轉的javascript,將這段嵌入到文章開頭即可。
<p>
<script type="text/javascript">// <![CDATA[
var ARTICLE_MAIN = document.getElementById("article-main");
if(ARTICLE_MAIN){
var delayMillis = 5000; //5 second
setTimeout(function(){
window.location= "跳轉頁面URL";//your code to be executed after 5 second
}, delayMillis);
}
// ]]></script>
</p>
<p><a href="文字連結URL">文章搬家囉,5秒後跳轉</a></p>
留言