為了備份blog,簡單寫了一個適用于blogjava等metaWeblog的blog備份工具,功能:

(1)備份post的正文到本地

(2)備份正文中的圖片、css文件到本地

(3)基于以上兩的步驟,修改相關(guān)的鏈接,實現(xiàn)本地脫機(jī)瀏覽

想到了但是未實現(xiàn)的功能:

(1)評論無法保存

(2)合適的話可以考慮以Eclipes RCP形式包裝

 

一、實現(xiàn)原理

(1)獲取post的方法:使用MetaWeblog提供的API接口

metaWeblog.getRecentPosts (blogid, username, password, numberOfPosts) returns array of structs,

Each struct represents a recent weblog post, containing the same information that a call to metaWeblog.getPost would return.

If numberOfPosts is 1, you get the most recent post. If it's 2 you also get the second most recent post, as the second array element. If numberOfPosts is greater than the number of posts in the weblog you get all the posts in the weblog.

 

(2) 使用正則表達(dá)式分析獲取下來的post,解析出post中包含的css和圖片文件的地址,執(zhí)行兩步操作

  • 根據(jù)地址,抓取圖片保存到本地
  • 修改post中的地址為本地保存地址

(3) 使用xml-rpc來簡化遠(yuǎn)程調(diào)用過程的編程

 

二、主要的代碼

public ArrayList<SimplePost> getAllPosts(String blogID, String name,String password, int num) throws XmlRpcException {
        ArrayList
<SimplePost> posts = new ArrayList<SimplePost>();
        Object[] params 
= new Object[] { blogID, name, password,new Integer(num) };
        Object[] result 
= (Object[]) client.execute("metaWeblog.getRecentPosts", params);

        
for (int i = 0; i < result.length; i++) {
            Map map 
= (Map) result[i];
            String postUrl 
= (String) map.get("link");
            String title 
= (String) map.get("title");
            String postId 
= (String) map.get("postid");

                        
// post的內(nèi)容
            String description = (String) map.get("description");
            
            Map
<String, String> images = new HashMap<String, String>();
            images 
= getImagesURL(description);
                    
            String newDes 
= handleImagesURL(description,postId);            
            String descriptioFileName 
= savePostContent(savePath, title,postId, newDes, css);

            SimplePost post 
= new SimplePost(postUrl, title, postId,descriptioFileName);
            
//從postContent獲取圖像的地址和名稱,以便獲取圖片并保存
            post.setImages(images);
            posts.add(post);
            log.debug(
"postID: " + postId + "postTitle :" + title);
        }
        
return posts;
    }

public static Map<String, String> getImagesURL(String description) {

      
  Map<String, String> map = new HashMap<String, String>();
        
// img 的正則表達(dá)式
     
  String imgPattern = "<\\s*img\\s+([^>]+)\\s*>";
        Pattern p 
= Pattern.compile(imgPattern, Pattern.CASE_INSENSITIVE);
        Matcher matcher 
= p.matcher(description);

        
// img src元素的正則表達(dá)式
        String srcPattern = "\\s*src\\s*=\\s*\"([^\"]+)\\s*\"";
         Pattern p2 = Pattern.compile(srcPattern, Pattern.CASE_INSENSITIVE);

        
while (matcher.find()) {
            Matcher matcher2 
= p2.matcher(matcher.group());
            
// 一定要find(),這是實際的匹配動作
            if (matcher2.find()) {
                String src 
= matcher2.group();
                log.info(src);
                
int i2 = src.lastIndexOf('/');
                
int i1 = src.indexOf("http");
                
if (i1 != -1) {
                    map.put(src.substring(i2 
+ 1, src.length() - 1), src
                            .substring(i1, src.length() 
- 1));
                }
            }
        }
        log.debug(
"圖片:" + map);
        
return map;
    }

/**
     * 替換description的圖片鏈接為本地的相對鏈接,結(jié)構(gòu)為blogFiles/images/postid/
     * 
     * 
@param description
     * 
@param userName
     * 
@param postId
     * 
@return
     
*/
    
public static String handleImagesURL(String description, String postId) {
        String tmp 
= description;        
        String address
="images/" + postId + "/";
        
        String imgPattern 
= "<\\s*img\\s+([^>]+)\\s*>";
        Pattern p 
= Pattern.compile(imgPattern, Pattern.CASE_INSENSITIVE);
        Matcher matcher 
= p.matcher(tmp);

        
// img src元素的正則表達(dá)式
        String srcPattern = "\\s*src\\s*=\\s*\"([^\"]+)\\s*\"";
        // String srcPattern = "\\s*src\\s*=\\s*\'([^\']+)\\s*\'";
        Pattern p2 = Pattern.compile(srcPattern, Pattern.CASE_INSENSITIVE);
        
while (matcher.find()) {
            Matcher matcher2 
= p2.matcher(matcher.group());
            
// 一定要find(),這是實際的匹配動作
            if (matcher2.find()) {
                String src 
= matcher2.group();
                log.info(src);                
                
int l2=src.lastIndexOf('/')+1;
                log.info(src.substring(l2,src.length()
-1));
                tmp
=tmp.replace(src,"  src=\""+address+src.substring(l2,src.length()-1)+"\"");                
            }
        }        
        
return tmp;
    }