1. 闲言碎语
好记性不如烂笔头。我们很多人喜欢写技术博客,构建知识库,然后把它们分享到网络平台,比如自建博客,主流博客平台,又或者记录在自己的笔记软件。
以下是我个人观点:
写技术博客,博文格式首选markdown。写makrdown,博文内容所见即所得比预览或者人脑渲染更爽。
博客发布平台,首选比较干净整洁的博客园。其他比如CSDN,简书,开源中国。很多人喜欢多平台一起发布,也没啥问题。
把博客当作代码,托管在github/gitee。把博客当作知识库,放在个人博客网站,笔记软件,导图软件,都是主流选择。
实际上我也想这么做,还没有付出更多的实际行动。
有人说,使用windowns系列操作系统+写作或者笔记软件来写,或者在线写不香吗?或者离线写好,同步软件同步,粘贴到在线平台不香吗?
实话说,挺香。
选择【创作】【保存】【同步】【分享】的组合方式很多,但是我还是喜欢找到适合自己的舒服的方式。
用typora写好了,右键分享一下,就能发布到博客,也挺香
我个人的组合方式:deepin+typora+cnblogs+wiznote
当然typora已经收费,wiznote已经发布Linux版本。更多更好的替代,都在排着队......
===================================================================
着重和正式强调:不要拿博客平台当图床用,后果自负!!!
===================================================================
2. 正式入题
之前也写过一篇比较全面的博客《Deepin15和20使用命令行快捷键鼠标右键发布博客至博客园和为知笔记》
在上面这篇博客中,你能在deepin上,用快捷键,用命令行,用右键三种姿势,来分享你的博客。
但是今天,我把代码改了改,2.0版本出来了。最重要的就是,能够上传图片了,香不香?
2.1 python3+xmrpc.client实现代码
以下是主要的代码:
#!/usr/bin/env python3
# -*- coding:utf-8 -*-
# ***************************************************************************
# *
# * @file:send_to_cnblogs.py
# * @author:liwanliang
# * @date:2021-12-08
# * @version 2.0
# * @description: Python Script
# * @Copyright (c) all right reserved
# *
# ***************************************************************************
# 本脚本发送博客至www.cnblogs.com
# --file 指定要上传的markdown博客文件
# --upload 指定要上传的(多个)图片
# ***************************************************************************
import sys
import xmlrpc.client #{'python3':"xmlrpc.client",'python2':"xmlrpclib"}
import mimetypes
import os
import json
import subprocess
from optparse import OptionParser
class CnblogsAPI():
"""
从配置文件读取用户的:url,帐号,密码
"""
def __init__(self,config_json):
self.__url,self.__user,self.__password = self.__read_config(config_json)
self.__cnblogs_api = xmlrpc.client.ServerProxy(self.__url)
self.__user_info = self.__cnblogs_api.blogger.getUsersBlogs('',self.__user,self.__password)
self.__user_blogid = self.__user_info[0].get('blogid')
def __read_config(self,config):
try:
with open(config,'r') as f:
data = json.load(f)
url = data.get('url')
user = data.get('user')
password = data.get('password')
if not all([url,user,password]):
print("配置文件未正确指定:url,user,password")
sys.exit(0)
except IOError:
print("未指定配置文件")
sys.exit(0)
return (url,user,password)
def get_all_blogs(self):
"""
获取全部博客:{title:postid}
"""
blogs_title_postid = {}
all_blogs = self.__cnblogs_api.metaWeblog.getRecentPosts(self.__user_blogid,self.__user,self.__password,0)
for blog in all_blogs:
blogs_title_postid.update({blog.get('title'):blog.get('postid')})
return blogs_title_postid
def __get_post_id(self,post_name):
"""
通过博客标题获取博客的post_id
"""
return self.get_all_blogs().get(post_name)
def upload_image_get_url(self,image):
"""
指定图片上传图片,返回图片的url
"""
with open(image,'rb') as f:
image_bits = xmlrpc.client.Binary(f.read())
image_type = mimetypes.guess_type(image)[0]
image_name = os.path.basename(image)
url = self.__cnblogs_api.metaWeblog.newMediaObject(
self.__user_blogid,
self.__user,
self.__password,
dict(bits=image_bits,name=image_name,type=image_type))
return url.get('url')
def edit_post(self,blog_file):
"""
指定博客文件上传,发送通知到操作系统
"""
with open(blog_file,'r') as blog:
blog_content = blog.read()
post_name = os.path.basename(blog_file)
post_id = self.__get_post_id(post_name)
post_info = {
'title':post_name,
'description':blog_content,
'categories':['[]','[Markdown]'],#默认不发送到博客园首页候选区,默认markdown格式
}
if post_id:
return self.__cnblogs_api.metaWeblog.editPost(
post_id,
self.__user,
self.__password,
post_info,True)
else:
return self.__cnblogs_api.metaWeblog.newPost(
self.__user_blogid,
self.__user,
self.__password,
post_info,True)
#****************************************************************************#
#上面的代码,主要是封装接口,复用性很强,ctrl+c,ctrl+v拿走就行。
# 下面的代码,就是个性化功能配置了
# 我个人的配置文件:
# 帐号密码配置文件,/home/liwl/.liwl/deepin/scripts/cnblogs.json
# conblogs.json内容:
#{
# "url":xxxx,
# "user":xxxx,
# "password":xxxx,
#}
# deepin分享博客成功后,发送一个系统通知,其icon图片
# /home/liwl/.liwl/deepin/picture/cnblogs.png
#****************************************************************************#
if __name__ == "__main__":
#脚本参数
parser = OptionParser()
parser.add_option("-f","--file",dest="filename")
parser.add_option("-u","--upload",dest="image",action="append")
(options,args) = parser.parse_args()
#加载配置文件
liwl_cnblogs = CnblogsAPI('/home/liwl/.liwl/deepin/scripts/cnblogs.json')
#获取markdown博客
markdown_blog = options.filename
if options.filename:
if liwl_cnblogs.edit_post(markdown_blog):
subprocess.run('notify-send -i /home/liwl/.liwl/deepin/picture/cnblogs.png "创建/更新博客,成功"',shell=True)
else:
subprocess.run('notify-send -i /home/liwl/.liwl/deepin/picture/cnblogs.png "创建/更新博客,失败"',shell=True)
#以下适合命令行发送
#else:
#subprocess.run('notify-send -i /home/liwl/.liwl/deepin/picture/cnblogs.png "未指定博客文件"',shell=True)
#获取多个图片
if options.image:
for img in options.image + args:
print(liwl_cnblogs.upload_image_get_url(img))
#以下代码适合命令行发送
#else:
#subprocess.run('notify-send -i /home/liwl/.liwl/deepin/picture/cnblogs.png "未指定(多个)图片"',shell=True)
上面的代码,保存到一个路径下:/home/liwl/.liwl/deepin/scripts/send_to_cnblogs.py
,
注意赋予一个执行权限:chmod +x /home/liwl/.liwl/deepin/scripts/send_to_cnblogs.py
2.2 deepin配置右键发送
创建一个desktop文件:
sudo vim /usr/share/deepin/dde-file-manager/oem-menuextensions/deepin-send.desktop
内容如下:
[Desktop Entry]
Type=Application
Name=发布文档到
Actions=SendTocnblogs;SendTonsccwx;SendTowiznote
X-DFM-MenuTypes=SingleFile
MimeType=text/markdown
[Desktop Action SendTocnblogs]
Name=博客园
Exec=python3 /home/liwl/.liwl/deepin/scripts/send_to_cnblogs.py --file %U
Icon=send-to
2.3 Typora配置上传图片
如下图配置即可
需要注意的是,【上传服务设定】-【命令】要写脚本绝对路径和参数,如下:
python3 /home/liwl/.liwl/deepin/scripts/send_to_cnblogs.py --upload
下面这张图,就是我截图之后,粘贴在typora,自动上传的哦
3. 原理分析
其实也没啥原理,主要是以前没有注意到metaWeblog.newMediaObject
这个接口,这两天研究了一下,发现这个接口,就把这个脚本重新修改了一下
简单理解:xmlrpc是一个协议,python实现了这个协议接口
python2的协议接口为:xmlrpclib,python3的协议接口包为:xmlrpc.client
博客园允许你使用这个协议来使用他们提供的接口,而且有个前提,你需要在自己的博客设置里面启用这个功能
博客设置——其他设置——勾选允许MetaWeblog博客客户端访问
Typora又恰好提供了使用命令或者脚本的方式来获取图片的url
所以,一切都是那么顺其自然,挺幸运
本篇博客就是在deepin系统下,写完了以后,右键发送到博客园的呢,右键
发送成功后,deepin上方会有如下图提示:
最后还是强调,不要把博客平台当作图床来用,否则后果自负