源码下载

前言

之前写过一片文章,typora 使用CSDN作为图床,用来存储 markdown 文章的图片资源文件。后来发现 typora 还可以自定义导出命令,那么也可以利用这个功能实现直接发布到CSDN平台,或者博客园平台。CSDN平台需要分析一下发布文章的接口,博客园可以直接利用 MetaWeblog API 来发布文章。我之前发布各个平台需要复制粘贴,但是程序员不做重复性质的劳动,哪怕仅仅是复制粘贴。

CSDN发布文章接口

CSDN 接口主要难点就是对请求头上x-ca-signature加了验证,参考我之前写的关于CSDN获取博客内容接口的x-ca-signature签名算法研究。 不过有意思的是,之前验证失败的时候会直接抛出验证错误的响应,现在是直接返回为空,不显示提示信息也是一种防逆向的策略。算法和以前几乎一样,不过有一些细微的差别,例如请求类型是POST,这个请求类型也是构成 x-ca-signature的一部分(加密前)。

csdnArticle.py

import requests
from urllib.parse import urlparse
import http.cookiejar as cookielib
import hashlib
import hmac
from base64 import b64decode,b64encode
import random
import sys
from markdown import markdown
import os
import csdnLogin
requests.packages.urllib3.disable_warnings() os.chdir(os.path.dirname(os.path.abspath(__file__))) headers = {
"user-agent": "Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.45 Safari/537.36",
'Content-Type': "application/json",
"origin": "https://editor.csdn.net",
"referer": "https://editor.csdn.net/",
"sec-ch-ua-platform": "Windows",
} def createUuid():
text = ""
char_list = []
for c in range(97,97+6):
char_list.append(chr(c))
for c in range(49,58):
char_list.append(chr(c))
for i in "xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx":
if i == "4":
text += "4"
elif i == "-":
text += "-"
else:
text += random.choice(char_list)
return text def get_sign(uuid,url):
s = urlparse(url)
ekey = "9znpamsyl2c7cdrr9sas0le9vbc3r6ba".encode()
to_enc = f"POST\n*/*\n\napplication/json\n\nx-ca-key:203803574\nx-ca-nonce:{uuid}\n{s.path}".encode()
sign = b64encode(hmac.new(ekey, to_enc, digestmod=hashlib.sha256).digest()).decode()
return sign def uploadArticle(articles):
for article in articles:
url = 'https://bizapi.csdn.net/blog-console-api/v3/mdeditor/saveArticle'
uuid = createUuid()
sign = get_sign(uuid,url)
headers = {}
headers['x-ca-key'] = "203803574"
headers['x-ca-nonce'] = uuid
headers['x-ca-signature'] = sign
headers['x-ca-signature-headers'] = "x-ca-key,x-ca-nonce"
session = requests.session()
session.cookies = cookielib.LWPCookieJar(filename='.cookie/csdn.txt')
session.cookies.load() with open(article,"r",encoding='utf8') as f:
data = f.read()
title = os.path.basename(article)[:-3] fields = {
"title": title,
"markdowncontent": data,
"content": markdown(data),
"readType": "public",
"tags": " ",
"status": 0,
"categories": "",
"type": "original",
"original_link": "",
"authorized_status": False,
"not_auto_saved": "1",
"source": "pc_mdeditor",
"cover_images": [],
"cover_type": 0,
"is_new": 1,
"vote_id": 0,
"pubStatus": "publish"
}
data = session.post(url,headers=headers,json=fields,verify=False)
print(data.json()["msg"]) if __name__ == '__main__':
uploadArticle(sys.argv[1:]) # x-ca-nonce: 5bbec46a-fae9-45f1-ab12-40e4e92c1901
# x-ca-signature: B2tpU+fIVigDzGba3rJYW6atH/jOZf4G3Ow/K2B64F4=
# 加密算法在app.chunk.12001b99.js 20126行

在CSDN上发布博客需要登录获取cookie:

csdnLogin.py

import requests
import http.cookiejar as cookielib
import psutil
import os
import re
os.chdir(os.path.dirname(os.path.abspath(__file__)))
requests.packages.urllib3.disable_warnings() def is_login():
session = requests.session()
try:
session.cookies = cookielib.LWPCookieJar(filename='.cookie/csdn.txt')
session.cookies.load() url = 'https://me.csdn.net/api/user/show'
response = session.post(url)
if response.json()['message'] == "成功":
return True
else:
return False
except Exception as e:
return False def login():
session = requests.session()
session.cookies = cookielib.LWPCookieJar(filename='.cookie/csdn.txt')
response = session.get('https://open.weixin.qq.com/connect/qrconnect?appid=wx0ae11b6a28b4b9fc&scope=snsapi_login&redirect_uri=https%3A%2F%2Fpassport.csdn.net%2Fv1%2Fregister%2FpcAuthCallBack%3FpcAuthType%3Dweixin&state=csdn&login_type=jssdk&self_redirect=default&style=white&href=https://csdnimg.cn/release/passport/history/css/replace-wx-style.css',verify=False)
uuid = re.findall('<img class="qrcode lightBorder" src="(.*?)" />',response.text)[0]
img_url = 'https://open.weixin.qq.com' + uuid
imgData = session.get(img_url).content
with open("qrcode.jpg","wb") as f:
f.write(imgData)
os.popen("qrcode.jpg") uuid = uuid.split('/')[-1]
url = 'https://long.open.weixin.qq.com/connect/l/qrconnect?uuid='+uuid
while True:
response = session.get(url,verify=False)
code = re.findall("window.wx_code='(.*?)'",response.text)
if code != ['']:
for proc in psutil.process_iter(): # 遍历当前process
try:
if proc.name() == "dllhost.exe": # 如果你展示图片的进程不是这个,可以对此进行修改
proc.kill() # 关闭该process
except Exception as e:
pass
break
time.sleep(1) url = 'https://passport.csdn.net/v1/register/pcAuthCallBack?pcAuthType=weixin&code=%s&state=csdn' % code[0]
session.get(url)
session.cookies.save() if not os.path.exists(".cookie"):
os.mkdir(".cookie")
if not os.path.exists(os.path.join(".cookie","csdn.txt")):
with open(os.path.join(".cookie","csdn.txt"),"w") as f:
f.write("") if not is_login():
login()

这里依然采用扫码登录的方式。

博客园平台

如果要使用博客园的 MetaWeblog API, 要在设置中进行简单的设置。

然后才可以使用,接口定义 很全面了,使用起来非常方便。

1. 上传图片

cnblogsImage.py

import xmlrpc.client
import ssl
import os
import json
import sys
ssl._create_default_https_context = ssl._create_unverified_context rootPath = os.path.abspath(os.path.dirname(__file__))
with open(os.path.join(rootPath,"cnblogs.json"),"rb") as f:
config = json.loads(f.read()) def uploadImage(images):
for image in images:
with open(image,"rb") as f:
imageData = f.read() baseName = os.path.basename(image)
suffix = baseName.split(".")[-1]
file = dict(
bits = imageData,
name = baseName,
type = f"image/{suffix}"
)
proxy = xmlrpc.client.ServerProxy(config["url"])
s = proxy.metaWeblog.newMediaObject('', config['username'], config['password'],file)
print(s["url"]) if __name__ == '__main__':
uploadImage(sys.argv[1:])

2.发布文章

cnblogsArticle.py

import xmlrpc.client
import ssl
import os
import json
import sys
ssl._create_default_https_context = ssl._create_unverified_context rootPath = os.path.abspath(os.path.dirname(__file__))
with open(os.path.join(rootPath,"cnblogs.json"),"rb") as f:
config = json.loads(f.read()) def uploadArticle(articles):
for article in articles:
with open(article,"r",encoding="utf8") as f:
data = f.read() title = os.path.basename(article)[:-3]
post = dict(
dateCreated = xmlrpc.client.DateTime(),
description = data,
title = title,
categories = ['[Markdown]'],
)
proxy = xmlrpc.client.ServerProxy(config["url"])
s = proxy.metaWeblog.newPost('', config['username'], config['password'],post,True)
# 输出文章连接
userName = config["url"].split("/")[-1]
print(f"https://www.cnblogs.com/{userName}/p/{s}.html") if __name__ == '__main__':
uploadArticle(sys.argv[1:])

使用

这里我使用的都是直接脚本调用,我不想进行打包,总感觉打包后执行效率变低。

如果要使用上传文章到博客圆,或者使用博客园图床,首先要对 cnblogs.json 进行修改:

{
"url": "https://rpc.cnblogs.com/metaweblog/Hellowshuo", //设置中的那个链接
"username": "Hello_wshuo", //用户名
"password": "12345678" //密码
}

配置使用typora图床:

命令:

D:/Python36/python.exe D:/software/Typora/command/cnblogsImage.py

这里最好都使用绝对路径进行配置,否则可能会有找不到脚本的问题。


上传文章到博客园:

命令:

D:/Python36/python.exe D:/software/Typora/command/cnblogsArticle.py ${currentPath}

${currentPath} 表示的是完整的markdown文件路径。


CSDN 图床配置:

命令:

D:/Python36/python.exe D:/software/Typora/command/csdnImage.py

CSDN 上传文章:

命令:

D:/Python36/python.exe D:/software/Typora/command/csdnArticle.py ${currentPath}

第一次上传CSDN文章或者使用CSDN图床,会提示扫码登录(登录成功后会自动关闭窗口),登录后自动保存cookie,下次登录直接调用cookie,等到cookie过期后会重新提示扫码登录。

typora实现多平台发布文章的更多相关文章

  1. 码字工作者的发文姿势—— 用MWeb+Markdown Here+七牛 轻松实现多平台发布

    码字工作者的发文姿势—— 用MWeb+Markdown Here+七牛 轻松实现多平台发布   1.对于写作你最头疼什么 对于大多数码字工作者来说,随时随地记录灵感,构思文章,集中书写,其实是一件令人 ...

  2. SEO优化:WordPress发布文章主动推送到百度,加快收录保护原创

    工作实在太忙,也没时间打理网站.最近公司额外交待了一些网站 SEO 方面的优化任务让我关注(这就是啥都要会.啥都要做的苦逼运维的真实写照了...). 于是抽空看了下百度站长平台,至少看到了2个新消息: ...

  3. Python + Selenium 自动发布文章(一):开源中国

    https://blog.csdn.net/qq_28804275/article/details/80891949 https://blog.csdn.net/qq_28804275/article ...

  4. 使用Word发布文章到 WordPress 博客

    使用Word发布文章到 WordPress 博客 我们都知道,WordPress 自带的编辑器功能比较弱,而使用 Word 编辑文档却功能强大.其实我们使用 Word 编辑好的文档也是可以直接发布到 ...

  5. tornado web高级开发项目之抽屉官网的页面登陆验证、form验证、点赞、评论、文章分页处理、发送邮箱验证码、登陆验证码、注册、发布文章、上传图片

    本博文将一步步带领你实现抽屉官网的各种功能:包括登陆.注册.发送邮箱验证码.登陆验证码.页面登陆验证.发布文章.上传图片.form验证.点赞.评论.文章分页处理以及基于tornado的后端和ajax的 ...

  6. 使用苏飞httphelper开发自动更新发布文章程序

    最近新上线了一个网站,专门收集网上签到赚钱,有奖活动等等的网站 我就要集分宝 http://www.591jfb.com.新建立 了一个栏目"每日更新",这样就需要每天都登录到网站 ...

  7. dedecms发布文章时多个Tag间分割逗号自动变成英文逗号

    dedecms发布文章时经常会添加多个Tag,我们输入汉字时总是喜欢使用全角的逗号,那么有没有办法使用JS脚本把输入的Tag间中文逗号变成英文逗号呢? dedecms发布文章时多个Tag间分割逗号自动 ...

  8. 黄聪:WordPress 后台发布文章时提示用户选择分类

    很多用户在后台发布文章,常常会忘记选择分类,所以很有必要添加一个提醒功能,如果没有选择分类,点击发布时,就显示一个提示信息.要实现这个功能,只要将下面的代码添加到主题的 functions.php 即 ...

  9. 织梦dedecms后台发布文章不自动更新首页与栏目列表页

    dedecms发文章不自动更新首页也列表页解决办法如下: 登陆dedecms后台,找到“系统”“系统基本参数”“性能选项”,把“arclist标签调用缓存”设置成0,然后把“发布文章后马上更新网站主页 ...

  10. (转)织梦dedecms后台发布文章提示“标题不能为空”

    问题症状:V5.7登录后台后,发布英文标题没问题,发布中文会提示“标题不能为空”. 问题根源:htmlspecialchars在php5.4默认为utf8编码,gbk编码字符串经 htmlspecia ...

随机推荐

  1. 将 Docker Engine 节点从 dockershim 迁移到 cri-dockerd

    官网地址:https://kubernetes.io/zh-cn/docs/tasks/administer-cluster/migrating-from-dockershim/migrate-doc ...

  2. 为什么阿里Java开发手册不推荐使用Timestamp

    开发手册 不推荐用java.sql.Date.java.sql.Time网上说的文章有很多. 参考文章:一文告诉你Java日期时间API到底有多烂 但为什么不推荐使用java.sql.Timestam ...

  3. 《吐血整理》高级系列教程-吃透Fiddler抓包教程(26)-Fiddler如何抓取Android7.0以上的Https包-上篇

    1.简介 众所周知,假如设备是android 7.0+的系统同时应用设置targetSdkVersion >= 24的话,那么应用默认是不信任安装的Fiddler用户证书的,所以你就没法抓到应用 ...

  4. centos7中配置java + mysql +jdk +使用jar部署项目

    centos7中配置java + mysql +jdk  +使用jar部署项目 思维导图 1. 配置JDK環境 1.1下载jdk安装包 Java Downloads | Oracle 1.2 将下载j ...

  5. 220722 T4 求和 /P4587 [FJOI2016]神秘数 (主席树)

    好久没打主席树了,都忘了怎么用了...... 假设我们选了一些数能构成[0,x]范围内的所有值,下一个要加的数是k(k<=x+1),那么可以取到[0,x+k]内的所有取值,所以有一种做法: 对于 ...

  6. 关于javascript:void(0) 在不用的浏览器当中的表现

    原因在于三款浏览器,对三个属性的处理顺序不同. Chrome顺序:onclick -> href -> target IE和Firefox顺序:onclick -> target - ...

  7. Linux基础_5_文件管理

    创建 touch 文件名 #创建文件 stat 文件名 #查看文件属性 touch -am 文件名 #更改文件的访问时间及修改时间 删除 rm -rf s/* #递归强制删除s目录下的所有内容(包括文 ...

  8. 如何使用IDEA自动生成类图

    然后再类里边按 Ctrl+Alt+U 然后就会生成类图,这个样子 然后怎样把生成的类图搞出来.当然是使用截图软件啦.微信上的截图软件和qq上的截图软件好像都不在阔以,你一点击截图按钮.生成的类图就会消 ...

  9. 前端框架Vue------>第二天学习(1)插槽

    欢迎加入刚建立的社区:http://t.csdn.cn/Q52km 加入社区的好处: 1.专栏更加明确.便于学习 2.覆盖的知识点更多.便于发散学习 3.大家共同学习进步 3.不定时的发现金红包(不多 ...

  10. 超好用的截图软件Snipaste(包含安装包)、如何设置Snipaste开机自启

    文章目录 1.设置开机自动启动 2.基本使用 链接: https://pan.baidu.com/s/1oR2qkOZl5-etPxr7kWip7Q 提取码:8888 1.设置开机自动启动 2.基本使 ...