Passion/Python

MetaWeblog를 이용한 포스팅

sunshout 2007. 6. 29. 01:21
테터툴즈는 metaWeblogAPI를 지원한다.

이는 metaWeblogAPI를 지원하는 클라이언트에서 블로그에 포스팅을 하거나
읽어오는 기능을 할 수 있게 해 준다.

이 API 를 이용하여 간단하게 Python에서 TatterTools에 포스팅하는 기능을 개발해 보았다.

사용되는 시나리오를 생각해 보면
나의 웹서버에서는 매일 아침 9시 네이버 OpenAPI 를 이용하여 내가 원하는 키워드를 검색한다.
예를 들어 OpenAPI를 이용하여 "신영밸류고배당" 이라는 글자가 들어가는 뉴스를 리턴받는다.

이를 html로 만든 다음 metaWeblogAPI를 이용하여 내 홈페이지에 포스팅을 하는 것이다.
우하하
이작업을 매일 아침 9시마다 돌리면 매일하면 내 펀드와 관련된 뉴스를 자동으로 블로그에 기록하게 되는 것이다.

코드는 생각보다 간단하게 작성할 수 있었다.

Python metaWeblogAPI - pymwa.py (Language : python)
  1. #----------------------------------------------------------------------------
  2. # python MetaWeblog API : pymwa.py
  3. #
  4. # Author : Choonho Son (choonho.son@gmail.com)
  5. #
  6. # Copyright (C) 2007-, Choonho Son
  7. #
  8. # This library is free software; you can redistribute it and/or
  9. # modify it under the terms of the GNU Lesser General Public
  10. # License as published by the Free Software Foundation; either
  11. # version 2.1 of the License, or (at your option) any later version.
  12. #
  13. # This library is distributed in the hope that it will be useful,
  14. # but WITHOUT ANY WARRANTY; without even the implied warranty of
  15. # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  16. # Lesser General Public License for more details.
  17. #
  18. # You should have received a copy of the GNU Lesser General Public
  19. # License along with this library; if not, write to the Free Software
  20. # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
  21. #
  22. # See the file COPYING for a complete copy of the LGPL.
  23. #-----------------------------------------------------------------------------
  24.  
  25. __version__ = "0.1"
  26.  
  27. import xmlrpclib
  28. import sys
  29.  
  30. #-------------------------------------
  31. # metaWeblogapi interface URL
  32. # TatterTools : http://www.example.com/tt/api
  33. #
  34. #-------------------------------------
  35. xmlrpcurl="http://sunshout.cafe24.com/blog/api"
  36.  
  37.  
  38. #--------------------------------------
  39. # About MetaWeblogAPI
  40. # Reference http://www.xmlrpc.com/metaWeblogApi
  41. #
  42. # 1. entry point
  43. # 1.1 newPost (blogid, username, password, struct, publish) returns string
  44. # 1.2 editPost(postid, username, password, struct, publish) returns true
  45. # 1.3 getPost (postid, username, password) returns struct
  46. #
  47. # 2. struct
  48. # same with element in RSS 2.0
  49. #   -----------------------------------------------------
  50. #   Element      Description            Example
  51. #   -----------------------------------------------------
  52. #   title       The title of item   Venice Film Festival
  53. #   link        The URL of the item http://nytimes.com/2004/12/07FEST.html
  54. #   description The item synopsis   contents (in Blog API)
  55. #   author      Email address       oprah\@oxygen.net
  56. #   category   
  57. #   comments
  58. #   enclosure   Describes a media object
  59. #               that is attached to the item
  60. #   guid        A string that uniquely
  61. #               itentifies the item
  62. #   pubData     published data
  63. #   source      The RSS channel that the item
  64. #                came from
  65. #
  66. # ****** In python, struct is dictionary ***********
  67. #   key             Example
  68. # -------------------------------------------------
  69. #   permaLink       http://sunshout.cafe24.com/blog/
  70. #   description     blala
  71. #   title
  72. #   mt_excerpt
  73. #   userid
  74. #   datePosted     <DateTime ''19700101T00:00:00' at 22f698>
  75. #   content
  76. #   link
  77. #   mt_allow_comments
  78. #   dateCreated
  79. #   postid
  80. #   dateModified
  81. #   categories    ['12']
  82. #   mt_allow_pings
  83. #
  84. #  To Do List
  85. #  1) explain struct
  86. #
  87. methods={}
  88.  
  89.  
  90. def getServer():
  91.     return xmlrpclib.Server(xmlrpcurl).metaWeblog
  92.  
  93.  
  94. #---------------------------------
  95. # Beautify plain text into html
  96. #
  97. # To Do:
  98. #       how to beautify plain text
  99. #
  100. # Current :
  101. #       send plain text
  102. #---------------------------------
  103. #def publish(text):
  104. #    import docutils.core
  105. #    return docutils.core.publish_parts(text, writer_name="html4css1")["body"]
  106.  
  107. #----------------------------------
  108. # new post
  109. #----------------------------------
  110. def newpost(account, args):
  111.     """Post an entry on webblog site."""
  112.    
  113.     struct = {"title":args[0], "categories":[args[1]],
  114.               "description":args[2]}
  115.     #------------------
  116.     # if publish work
  117.     #-----------------
  118.     #         "description":publish(args[2])}
  119.  
  120.  
  121.     # newPost(postId, username, password,
  122.     #         {title, description, categories}, publish)
  123.     postid = getServer().newPost("", account[0], account[1], struct, True)
  124.     return postid
  125.  
  126. # register as "NEW"
  127. methods["NEW"]=newpost
  128.        
  129. #-------------------------------------
  130. # edit post
  131. #-------------------------------------
  132. def editpost(account, args):
  133.     """Edit an existed entry """
  134.    
  135.     struct = {"title":args[1], "categories":[args[2]],
  136.               "description":args[3]}
  137.     # "description":publish(args[3])}
  138.     # editPost(postId, username, password,
  139.     #          {title, description, categories}, publish)
  140.     ret = getServer().editPost(args[0], account[0], account[1], struct, True)
  141.     print "modified post has be saved"
  142.  
  143. # register as "EDIT"
  144. methods["EDIT"]=editpost
  145.  
  146. #-------------------------------------
  147. # get post
  148. #-------------------------------------
  149. def getpost(account, args):
  150.     """get an post from args
  151.     args = post number
  152.     """
  153.     # getPost(postid, username, password)
  154.     # return struct
  155.     struct = getServer().getPost(args[0], account[0], account[1])
  156.     return struct
  157.  
  158. methods["GET"]=getpost
  159.  
  160. #----------------------------------------
  161. # get categories if exist
  162. #----------------------------------------
  163. def getcategories(account, args):
  164.     """get categories if exist"""
  165.     # getCategories(blogid, username, password)
  166.     # return list of struct
  167.     # struct = {description, htmlURL, rssURL element}
  168.     category_list = getServer().getCategories('',account[0], account[1])
  169.     return category_list
  170.  
  171. methods["CATEGORIES"] = getcategories
  172.  
  173. #----------------------------------------
  174. # attach media object
  175. #----------------------------------------
  176. def newmediaobject(account, args):
  177.     """Upload an multimedia to blog site."""
  178.    
  179.     struct = {"name":args[0], "type":type[1], "bits":bits[2]}
  180.     # newMediaObject(postId, username, password,
  181.     #                {name, type, bits})
  182.     upload = getServer().newMediaObject("", account[0], account[1], struct)
  183.     print "url of upload:", upload["url"]
  184.  
  185. # register as "MEDIA"
  186. methods["MEDIA"]=newmediaobject
  187.  
  188.  
  189. def getrecentposts(account, args):
  190.     """Get recently posted entries."""
  191.  
  192.     # getRecentPosts(postid, username, password, numposts)
  193.     posts = getServer().getRecentPosts("", account[0], account[1],
  194.                                       len(args) == 0 and 5 or int(args[0]))
  195.     # pretty print posts
  196.     import time
  197.     for p in posts:
  198.         print
  199.         print "postid:", p["postid"]
  200.         print "title:", p["title"]
  201.         print "created date:", \
  202.             time.strftime("%Y-%m-%d", \
  203.             time.strptime(p["dateCreated"].value, "%Y%m%dT%H:%M:%S"))
  204.  
  205. # register as "LIST"
  206. methods["LIST"]=getrecentposts
  207.        
  208.  
  209.  
  210. if __name__ == "__main__":
  211.     # ---------------------------------------------
  212.     # use if you want get from command line
  213.     # ---------------------------------------------
  214.     #method = sys.argv[1]
  215.     #args = sys.argv[2:]
  216.  
  217.     #-----------------------
  218.     # TatterTools (ID, PW)
  219.     #
  220.     # ex) account = ['haha@paran.com', 'hahapassword']
  221.     #-----------------------
  222.     account = ['put your id','put your password']
  223.    
  224.  
  225.    
  226.     #---------------------------
  227.     # example post's content
  228.     # if category name is not correct,
  229.     # then post without category
  230.     #---------------------------
  231.     method = "NEW"
  232.     mytitle = 'Automatic Fund crawler'
  233.     mycategories = 'Asset/Fund'
  234.     mytext = """
  235. <b>some contents</b>
  236. html does not work
  237. """
  238.     args = [mytitle,mycategories,mytext]
  239.     methods[method](account, args)
  240.  
  241.     #-------------------------------------
  242.     # example : get post
  243.     # post number : http://sunshout.cafe24.com/blog/128
  244.     #
  245.     #-------------------------------------
  246.     #print methods["GET"](account,[128])
  247.  
  248.  
  249.     #-------------------------------------
  250.     # example : get categories list
  251.     #-------------------------------------
  252.     #print methods["CATEGORIES"](account,[])
  253.  
  254.