上周末花了两天时间,终于把博客迁移了过来,所有文章与图片都完整地保留在新博客中。
其实很早就有把博客转成独门博客的想法,一直拖没实现。最近正好趁百度空间升级,来了情绪,索性一下子换了过来。对了百度空间,用了四年了,感情也非常深,但是它有几个明显的缺点,让我一直耿耿于怀。首先就是写文章的时候,特别是写技术性的文章,帖代码没有格式化代码的功能,导致帖出来的代码格式非常乱,很难看。而且编辑器功能也比较弱,没办法定制。还有由于众所周知的原因,我发布的很多文章时不时会被和谐掉。前两天整理博客文章的时候,发现一共掉了一百多篇文章,可恶啊。不过还好百度官方提供了一个导出所有文章的功能,所以才很容易把所有文章迁移过来。还有百度的图片上传功能,简直弱爆了,上传的时候极不稳定,速度也不快,而且还限制大小为500K,超过500K它强制性压缩你的图片,当然压缩后的图片简直不能看。所以我发图片的时候还会多一道工序,就是检查大小,如果发现超过了500K,就用convert命令压缩一下图片。在发新文章的时候,它还会对文章内容进行关键词检查,发现在敏感词,就不让发布。
对此我还专门写了一个python脚本,专门对内容进行敏感词检查,我之前的文章有讲过。但是有的敏感词,并不在我的收录范围之内, 这时候就采用比较笨的办法“二分法”来找敏感词,就是一段一段地删除,看删除到哪里的时候就能发表成功,那么说明关键词就在那一段里面,逐一缩小范围,直到找出敏感词。有时候就为这一点就折腾好长时间才能发表成功,真是蛋疼。最后导火索就是百度空间即将进行的升级,把一个博客性质的系统活生生地变成了社交化的工具,类似点点网的那种,非常不爽,找不到那种个人领地的感觉了。还有就是升级的过程中,又把我的图片什么的搞丢了。百度每次升级都会出级这种技术问题,上一次丢了我好多文章,刚发的就莫名其妙地不见了,升级完后才恢复回来。
换博客还有一个好处,就是有了自己的服务器,这样很多东西就有条件捣鼓了,自己的一些想法,就随时可以写出来放在服务器上面跑。虽然发费了一些经济上的代价,不过我觉得就长远来说,肯定是值的。有的事情,迟早是要迈出第一步,能早就早点。
上面讲了迁移博客的背景与原因,下面着重讲一讲迁移的过程。由于文章与图片比较多,文章有将近2000篇,图片2500张左右,所以不可能人工手动来做这个事情啦。为此我写了很多个脚本,用了很多命令行工具,如grep/ack,sed,vim等。由于百度官方已经提供完整的文章打包下载功能,所以文章就省事了,虽然我也写过下载文章的python脚本,但是下载不了那些设置成隐私的文章。基于现有的文章,我迁移方案思路如下:
1、整理百度打包的文章,将文章的文件、发表时间、文章名按一定格式组织好,以便进行后处理。
2、获取文章分类,对每篇文章,从网上拉取文章的标题与分类,并与第一步中的文章名进行匹配,将文章分类加到第一步生成的列表中去。
3、对第二步处理后的列表进行分类检查,因为文章标题匹配肯定会有一些文章匹配不上,还有隐私的文章肯定匹配不上,对这些单独进行手动添加分类
4、对文章内容里面的图片链接进行处理。将图片下载到本地,然后将链接替换成相对路径(后面会结合wordpress系统的路径再一次处理)。
5、经过以上步骤,所有的数据都准备好了,最后一步就是将这些数据按照wordpress数据库指定的格式存到wordpress数据库中去。
第一步:
主要对打包下载好的索引文件blog_index.html进行处理,去掉不必要的信息,整理成比较规律的列表。这一步主要利用vim来实现,用vim的正规匹配替换功能。例如:
1 2 | :%s/<\li>/<\ /li >\r /g #把li后进行换行 :%s/<li class= ".\{-}href =" //g #.\{-}为vim的非贪婪匹配 |
按照类型的步骤后,最后的效果如下:
第二步:
主要写了一个python脚本来实现下载分类信息 getCategory.py:
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 | # coding=utf-8 import urllib #import os import codecs import thread def GetURLS(url): list0 = [] s1 = '<div class=tit><a href="' content = '' try : content = urllib.urlopen(url).read().decode( 'gbk' ) except : print url i = content.find(s1) if (i <> - 1 ): content = content[i + len (s1): len (content)] while True : i = content.find(s1) if (i = = - 1 ): break content = content[i + len (s1): len (content)] i = content.find( '"') str0 = content[0:i] str0 = 'http://hi.baidu.com'+str0 list0.append(str0) content = content[i:len(content)] return list0 def GetContent(url): s1 = u'title="查看该分类中所有文章">类别:' s2 = '</a>' #print url content = urllib.urlopen(url).read().decode('gbk') #print content i = content.find('<title>')+7 content = content[i:len(content)] j = content.find('_') title = content[0:j] i = content.find(s1) content = content[i+len(s1):len(content)] j = content.find(s2) content = content[:j] return content, title def ToHTML(content, name): name = name.replace('*', '') name = name.replace('/', '') name = name.replace('\\', '') name = name.replace(':', '') name = name.replace('?', '') name = name.replace('"' , '') name = name.replace( '<' , '') name = name.replace( '>' , '') name = name.replace( '|' , '') name = name.replace( '#' , 'Sharp' ) filea = codecs. open ( 'category.txt' , 'a' , 'utf-8' ) filea.write(name + ' | ' + content + '\r\n' ) filea.close() def downOne(url, sum0): content, title = GetContent(url) #mylock.acquire() #获取同步锁 #title = str(sum0)+','+title #print title #mylock.release() #释放同步锁 ToHTML(content, title) print title HiName = 'hacklzt' i = 0 #博客分页 sum0 = 0 #文章总数 #多线程同步锁 mylock = thread.allocate_lock() headurl = '' while True : list0 = GetURLS(baseurl + str (i)) #print list0 if ( len (list0) = = 0 ): break if (list0[ 0 ] = = headurl): break headurl = list0[ 0 ] for j in list0: sum0 = sum0 + 1 thread.start_new_thread(downOne,(j, sum0)) #downOne(j, sum0) i = i + 1 |
下载后的格式如下图 category.txt:
然后将上面的结果与上一步的列表进行匹配整合的python脚本 sortCategory.py:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 | #!/bin/bash #encoding=utf-8 categorys = {} content = '' nocat = 0 for line in open ( 'category.txt' ): tmp_arr = line.split( '|' ) categorys[tmp_arr[ 0 ].strip()] = tmp_arr[ 1 ].strip() for line in open ( 'blog_index.html' ): tmp_arr = line.split( '|' ) title = tmp_arr[ 2 ].strip() cat = title in categorys.keys() and categorys[title] or '' if not title in categorys.keys(): nocat = nocat + 1 content + = line.strip() + ' | ' + cat + '\r\n' print content open ( 'index_blog-cat.html' , 'w' ).write(content) print 'NO:' + str (nocat) #打印不匹配的总数 |
第三步:
检查有哪些文章没有匹配上分类,打印出来,同样也是python脚本来完成 checkCategory.py:
1 2 3 4 5 6 7 | #!/bin/bash #encoding=utf-8 for line in open ( 'index_blog-cat.html' ): tmp_arr = line.strip().split( '|' ) if tmp_arr[ - 1 ].strip() = = '': print line |
合并后的格式如图:
图片的文章顺序是我颠倒了的,因为后插入到数据库中时,要先插入老的文章,颠倒文本内容顺序也很简单,一个命令搞定:
tac index_blog- cat .html > index_blog- cat -rsort.html |
第四步:
这一步将文章内容(百度打包里面的html文件)中的图片链接进行替换,主要利用grep、ack与sed命令接合来实现,例如:
sed -i 's/src="pics\/hiphotos.baidu.com\/hacklzt\/pic\/item/src="../wp-content/uploads/hibaidu/g' blog/*.html #注意\的转义作用 |
考虑到不仅要替换链接,还要将图片下载到本地,于是写了一个shell脚本来完成 pics.sh:
1 2 3 4 5 6 7 8 9 10 11 12 | #/bin/bash #encoding=utf8 grep -o -P ' pics.url #将图片地址保存 while read line; do fname=` echo ${line} | awk -F/ '{print $NF}' ` #找出图片地址的文件名 echo ${line} ' ' ${fname} regurl=${line // \ // \\\/} #正则匹配时,将/替换成\/ sed -i "s/${regurl}/pics\/${fname}/g" blog/*.html #正则替换图片地址 #echo "curl -o pics/${fname} ${line} > /dev/null" #下载图片 curl -o pics/${fname} ${line} > /dev/null #下载图片 done < pics.url #从文件中读取每一行进行处理 |
第五步:
到现在为止,我们要做的数据准备工作已经完成了。最后写了一个php脚本,把文章内容与时间等信息,存到wordpress相应的数据表中。post2wp.php内容如下:
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 | <!--?php date_default_timezone_set( 'Asia/Chongqing' ); $index_file = 'index_blog-cat.html' ; $f_handle = fopen ( $index_file , 'r' ); while (! feof ( $f_handle )){ $line = fgets ( $f_handle ); if ( empty ( $line )) break ; $line_arr = explode ( '|' , $line ); $blog_file = trim( $line_arr [0]); $date_time = trim( $line_arr [1]); $title = htmlspecialchars(trim( $line_arr [2])); $cat = trim( $line_arr [3]); processBlog( $blog_file , $title , $date_time , $cat ); } $sql = 'update wp_term_taxonomy w1 set w1. count = (select count (*) from wp_term_relationships where term_taxonomy_id = w1.term_taxonomy_id)'; $res = mysql_query( $sql ); //更新每个目录下面有多少文章 function processBlog( $blog_file , $title , $date_time , $cat ){ $cat_arr = array ( '默认分类' => 1, '工具教程' => 3, '技术文章' => 4, '个人日记' => 5, '编程相关' => 6, 'delphi编程' => 7, '精品文章' => 8, '原创作品' => 9, '学习笔记' => 10, '网页编程' => 11, '.net编程' => 12 ); $handle = fopen ( $blog_file , 'r' ); $blog_content = fread ( $handle , filesize ( $blog_file )); $blog_content = mysql_real_escape_string( $blog_content ); $post_time = strtotime ( $date_time ); $post_time_gmt = date ( 'Y-m-d h:i:s' , $post_time - 8*3600); //echo $post_time_gmt; exit(); $sql = "INSERT INTO wp_posts ( post_author, post_date, post_date_gmt, post_content, post_title, post_excerpt,post_status, comment_status, ping_status, post_password, post_name, to_ping, pinged, post_modified, post_modified_gmt, post_content_filtered, post_parent, guid, menu_order, post_type, post_mime_type, comment_count) VALUES (" . "1,'{$date_time}', '{$post_time_gmt}', '{$blog_content}', '{$title}'," . "'', 'publish', 'open', 'open', ''," . "'', '', '', '{$date_time}', '{$post_time_gmt}', " . "'', 0, '', 0, 'post', " . "'', 0);" ; //echo $sql; exit(); mysql_connect( 'localhost' , 'root' , 'hacklzt' ); mysql_select_db( 'wp_blog' ); mysql_query( 'SET NAMES UTF8;' ); $res = mysql_query( $sql ); //插入文章 if ( empty ( $res )){ echo "$title 失败" ; } $ins_id = mysql_insert_id(); if ( array_key_exists ( $cat , $cat_arr )){ $sql = "INSERT INTO wp_term_relationships (object_id, term_taxonomy_id, term_order) " . "VALUES ($ins_id, $cat_arr[$cat], 0);" ; $res = mysql_query( $sql ); //插入此文章的分类 if ( empty ( $res )){ echo "$title 分类失败" ; } else { } } else { echo "$title 分类失败" ; } } ?> |
用命令 php post2wp.php,就可以直接运行该php文件。
OK,收工。
此外,现发现文章里面的链接不对,可以用SQL语句来修正:
UPDATE wp_posts SET post_content = REPLACE ( post_content, '原内容' , ' 新内容' ) ; |
其实上面的脚本我是调试了很久才最终完成的,所以程序不是写出来的,是调出来的,哈哈。