原文地址:http://shajunxing.tpddns.cn:8888/web/blog/2018-03-13-Python3使用MetaWeblog接口读写CSDN博客/index.html
MetaWeblog API基于XMLRPC,支持通过编程方式对博客进行读写操作。以下是相关介绍和文档。
- XMLRPC的介绍:http://xmlrpc.scripting.com/
- MetaWeblog的介绍:http://xmlrpc.scripting.com/metaWeblogApi.html
- CDSN的MetaWeblog接口说明:http://write.blog.csdn.net/xmlrpc/index
- Python3内置的xmlrpc.client模块文档:https://docs.python.org/3/library/xmlrpc.client.html
CSDN的接口可以直接使用浏览器打开查看说明,虽然写得很粗略,但是可以通过代码进行试验获知如何使用。
首先看这两个接口:blogger.getUserInfo
和blogger.getUsersBlogs
,都是三个参数,key
、username
和password
,经过试验,key
没有用,可以取任意字符串,但是不能为None
,username
和password
分别是登录CSDN的用户名和密码。接口调用的Python代码很简单,首先通过接口URL获取一个ServerProxy
对象,然后在该对象上执行方法即可,如下所示:
p = xmlrpc.client.ServerProxy(接口URL)
print(p.blogger.getUserInfo('', 用户名, 密码))
print(p.blogger.getUsersBlogs('', 用户名, 密码))
其中,接口URL就是http://write.blog.csdn.net/xmlrpc/index,在创建ServerProxy对象的时候也可以加上参数verbose=True
,这样就能看到HTTP请求响应内容。
查看输出,得知返回的都是结构类型,从中可以读出很多信息,例如用户ID、昵称、邮件地址等,这些应该和注册所填的信息是一致的。blogger.getUsersBlogs
获得的是一个数组结构,只有一个元素,所以猜测这里所谓的Blog不是指文章,而是博客这样一个全局的概念。数组意味着某个人在某个网站上的博客可能有多个,虽然一般一个网站只能有一个博客,我还没有见到过能开多个博客的情况。不废话了,总之,其中得到的blogid
非常重要,因为其它接口需要用到。
通过metaWeblog.getCategories
方法可以获取所有的文章分类:
print(p.metaWeblog.getCategories(blogid, 用户名, 密码))
返回的是数组结构,其中每一项对应一个分类。因为我的文章不分类,所以没有仔细研究。
接下来看看如何对文章进行增删改操作。首先得知道MetaWeblog用什么样的结构描述一篇文章。继续做试验,用metaWeblog.getPost
方法抓一篇文章看看。其中第一个参数是postid
,意为文章的ID,我猜测就是使用浏览器查看文章时,比如URL是http://blog.csdn.net/xxx/article/details/123456,那么postid
应该就是123456
,试试看:
print(p.metaWeblog.getPost('123456', 用户名, 密码))
注意,根据接口说明,postid
应该是字符串类型,不要忘了引号。
经过试验,这个接口不单单能读自己的文章,还能读其他人的,所以或许可以在爬虫中用到?
返回的结构大致是这样的:
{'categories': [],
'dateCreated': <DateTime ...>,
'description': '<p>文章内容...</p>',
'title': '文章标题...'}
从中可以看到,title
是文章标题,description
是HTML格式的文章内容,虽然这个名字真的非常文不对题,但我们要适应,没办法。
这个结构在接口说明中称为PostInfo
,在新增和修改文章中用到。
新增文章使用metaWeblog.newPost
方法,查看接口说明,有5个参数,其中的post
就是上述的PostInfo
结构,经过测试,title
、description
和categories
是必填的,最后一个参数publish
要填True
,即:
p.metaWeblog.newPost(blogid, 用户名, 密码, {
'title': 文章标题,
'description': 文章内容,
'categories': [],
}, True)
返回新建文章的postid
,注意,是字符串不是数字。
修改文章使用metaWeblog.editPost
方法,参数和上面类似,只不过blogid
换成了postid
,这是很显然的,经过测试,CSDN返回的XMLRPC格式错误地用True/False表示布尔值,而按照标准应该是1/0,所以Python会解析错误。不管了,反正成功就行。代码如下:
p.metaWeblog.editPost(postid, 用户名, 密码, {
'title': 文章标题,
'description': 文章内容,
'categories': [],
}, True)
删除文章使用blogger.deletePost
方法,查看接口说明,猜想那个key
参数肯定是没用的,然后要删除文章肯定得指定文章的postid
,这是很显然的。经过测试,CSDN返回一个更恶心的500错误,不过删除倒是成功了,也就无所谓了。这里吐槽一下,比较人家WordPress的API(https://codex.wordpress.org/XML-RPC_MetaWeblog_API),国内的可见有多烂了。
p.blogger.deletePost('', postid, 用户名, 密码, True)
现在文章的增删改搞定,不过还只能处理文本信息,图片怎么办?根据接口说明,metaWeblog.newMediaObject
是可以上传图片的,不过我并不想试验,反正用不到,也不愿意再面对那些乱七八糟的服务器错误。
最后,我写了一个简单的类:
class CsdnMetaWeblog():
def __init__(self, username, password, verbose=False):
self.un = username
self.pw = password
self.sp = xmlrpc.client.ServerProxy(
'http://write.blog.csdn.net/xmlrpc/index', verbose=verbose)
self.bid = self.sp.blogger.getUsersBlogs(
'', self.un, self.pw)[0]['blogid']
def newPost(self, title, content):
return self.sp.metaWeblog.newPost(self.bid, self.un, self.pw, {
'title': title,
'description': content,
'categories': [],
}, True)
def editPost(self, postid, title, content):
try:
return self.sp.metaWeblog.editPost(postid, self.un, self.pw, {
'title': title,
'description': content,
'categories': [],
}, True)
except TypeError:
# CSDN的返回值把boolean类型错写成True/False,按照标准应该是1/0
return True
except Exception:
return False
def deletePost(self, postid):
try:
return self.sp.blogger.deletePost('', postid, self.un, self.pw, True)
except xmlrpc.client.ProtocolError:
# 返回500,不知道什么鬼问题,不过删除成功
return True
except Exception:
return False
用法很简单啦:
mw = CsdnMetaWeblog(用户名, 密码)
# 新增文章
postid = mw.newPost(文章标题, 文章内容)
# 修改文章
mw.editPost(postid, 修改的标题, 修改的内容)
# 删除文章
mw.deletePost(postid)