Python3使用MetaWeblog接口读写CSDN博客

原文地址:http://shajunxing.tpddns.cn:8888/web/blog/2018-03-13-Python3使用MetaWeblog接口读写CSDN博客/index.html

MetaWeblog API基于XMLRPC,支持通过编程方式对博客进行读写操作。以下是相关介绍和文档。

CSDN的接口可以直接使用浏览器打开查看说明,虽然写得很粗略,但是可以通过代码进行试验获知如何使用。

首先看这两个接口:blogger.getUserInfoblogger.getUsersBlogs,都是三个参数,keyusernamepassword,经过试验,key没有用,可以取任意字符串,但是不能为Noneusernamepassword分别是登录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结构,经过测试,titledescriptioncategories是必填的,最后一个参数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)
已标记关键词 清除标记
©️2020 CSDN 皮肤主题: 技术黑板 设计师:CSDN官方博客 返回首页