首页 > 其他分享 >博客园上传本地markdown文件

博客园上传本地markdown文件

时间:2023-07-09 21:44:20浏览次数:32  
标签:md markdown text 博客园 application file path 上传 image

cnblog_upload/cnblog_upload.command

#! /bin/bash
# source /Users/song/Code/script_python/pycnblog-master/venv/bin/activate
echo -n '请拖入一个md文件或者文件夹:'
read file_path
/Users/song/Code/script_python/cnblog_upload/venv/bin/python3 /Users/song/Code/script_python/cnblog_upload/src/main.py $file_path


cnblog_upload/src/history2anki.py

import os

from server.cnblog_server import server
from conf.conf import ST
from file.csv import write2csv


if __name__ == "__main__":
    recent_posts = server.metaWeblog.getRecentPosts(ST.blog_id,ST.username ,ST.password, 19)

    # 输出到桌面 
    out_md_path = os.path.join("/Users/song/Desktop" ,'anki.csv')

    for post in recent_posts:
        link = post['link']
        content = post['description'].split('\n')[0]
        write2csv(out_md_path,f'{content}\t<a href={link}>{content}</a>\n')

cnblog_upload/src/main.py

import asyncio
import time
import os
import sys

from img.unload_img import find_md_img,replace_md_img,upload_md_img
from server.cnblog_server import server
from conf.conf import ST
from file.csv import write2csv,generate_file_name
from file.md import read_md,get_md_files

net_images = []  # 图片上传后url
image_count = 1  # 图片计数



def get_image_url(t):
    """回调,获取url"""
    global image_count
    global net_images
    url = t.result()['url']
    print(f'第{image_count}张图片上传成功,url:{url}')
    net_images.append(url)
    image_count += 1




def upload_img(md_path,md):
    global net_images
    local_images = find_md_img(md)

    if local_images:  # 有本地图片,异步上传
        tasks = []
        for li in local_images:
            image_full_path = os.path.join(dir_name, li)
            task = asyncio.ensure_future(upload_md_img(image_full_path))
            task.add_done_callback(get_image_url)
            tasks.append(task)
        loop = asyncio.get_event_loop()
        loop.run_until_complete(asyncio.wait(tasks))
        loop.close()
        image_mapping = dict(zip(local_images, net_images))
        md = replace_md_img(md_path, image_mapping)
    else:
        print('无需上传图片')
    return md






if __name__ == "__main__":

    if len(sys.argv) == 1:
        exit(-1)

    file_or_dir_path = sys.argv[1]
    if os.path.isfile(file_or_dir_path):
        md_paths = [file_or_dir_path]
        dir_name = os.path.dirname(file_or_dir_path)
    else:
        md_paths = get_md_files(file_or_dir_path)
        dir_name = file_or_dir_path

    for md_path in md_paths:
        md = read_md(md_path)
        md = upload_img(md_path,md)
        title, _ = os.path.splitext(os.path.basename(md_path))  # 文件名作为博客标题

        post = dict(description=md, title=title, categories=['[Markdown]'],mt_keywords='anki')
        server.metaWeblog.newPost(ST.blog_id ,ST.username , ST.password , post, ST.publish)
        print(f"markdown上传成功, 博客标题为'{title}', 状态为'已发布', 请到博客园后台查看")

        time.sleep(3)
        recent_posts = server.metaWeblog.getRecentPosts( ST.blog_id , ST.username,ST.password, 1)

        # 获取所有标题,需要处理HTML转义字符
        out_md_path = os.path.join(dir_name,generate_file_name())

        for post in recent_posts:
            anki_title = post['title'] 
            link = post['link']
            content = post['description'].split('\n')[0]
            write2csv(out_md_path,f'{anki_title}\t<a href={link}>{content}</a>\n')
            break

        time.sleep(3)



cnblog_upload/src/file/md.py

import os

def get_md_files(folder_path):
    markdown_files = []
    for file_name in os.listdir(folder_path):
        if file_name.endswith(".md"):
            markdown_files.append(os.path.join(folder_path, file_name))
    return markdown_files



def read_md(path):
    with open(path, encoding='utf-8') as f:
        md = f.read()
        return md


cnblog_upload/src/file/csv.py

from datetime import datetime


def generate_file_name():
    # Get the current time
    now = datetime.now()
    # Format the time as a string
    time_str = now.strftime('%Y-%m-%d_%H-%M-%S')
    # Create the file name
    file_name = f'Z_{time_str}.csv'
    return file_name




def write2csv(path,msg):
    with open(path, "a", encoding='utf-8') as f:  # 打开文件
        f.write(msg)


cnblog_upload/src/server/cnblog_server.py

import xmlrpc.client
from conf.conf import ST

try:
    server = xmlrpc.client.ServerProxy(ST.blog_url)
except Exception as e:
    e = str(e)
    if 'unsupported XML-RPC protocol' in e:
        print('请查看config.yaml文件中的blog_url,应该是这个URL地址没设置对')

cnblog_upload/src/img/mime.py

mime_mapping = {
    ".323": "text/h323",
    ".asx": "video/x-ms-asf",
    ".acx": "application/internet-property-stream",
    ".ai": "application/postscript",
    ".aif": "audio/x-aiff",
    ".aiff": "audio/aiff",
    ".axs": "application/olescript",
    ".aifc": "audio/aiff",
    ".asr": "video/x-ms-asf",
    ".avi": "video/x-msvideo",
    ".asf": "video/x-ms-asf",
    ".au": "audio/basic",
    ".application": "application/x-ms-application",
    ".bin": "application/octet-stream",
    ".bas": "text/plain",
    ".bcpio": "application/x-bcpio",
    ".bmp": "image/bmp",
    ".cdf": "application/x-cdf",
    ".cat": "application/vndms-pkiseccat",
    ".crt": "application/x-x509-ca-cert",
    ".c": "text/plain",
    ".css": "text/css",
    ".cer": "application/x-x509-ca-cert",
    ".crl": "application/pkix-crl",
    ".cmx": "image/x-cmx",
    ".csh": "application/x-csh",
    ".cod": "image/cis-cod",
    ".cpio": "application/x-cpio",
    ".clp": "application/x-msclip",
    ".crd": "application/x-mscardfile",
    ".deploy": "application/octet-stream",
    ".dll": "application/x-msdownload",
    ".dot": "application/msword",
    ".doc": "application/msword",
    ".dvi": "application/x-dvi",
    ".dir": "application/x-director",
    ".dxr": "application/x-director",
    ".der": "application/x-x509-ca-cert",
    ".dib": "image/bmp",
    ".dcr": "application/x-director",
    ".disco": "text/xml",
    ".exe": "application/octet-stream",
    ".etx": "text/x-setext",
    ".evy": "application/envoy",
    ".eml": "message/rfc822",
    ".eps": "application/postscript",
    ".flr": "x-world/x-vrml",
    ".fif": "application/fractals",
    ".gtar": "application/x-gtar",
    ".gif": "image/gif",
    ".gz": "application/x-gzip",
    ".hta": "application/hta",
    ".htc": "text/x-component",
    ".htt": "text/webviewhtml",
    ".h": "text/plain",
    ".hdf": "application/x-hdf",
    ".hlp": "application/winhlp",
    ".html": "text/html",
    ".htm": "text/html",
    ".hqx": "application/mac-binhex40",
    ".isp": "application/x-internet-signup",
    ".iii": "application/x-iphone",
    ".ief": "image/ief",
    ".ivf": "video/x-ivf",
    ".ins": "application/x-internet-signup",
    ".ico": "image/x-icon",
    ".jpg": "image/jpeg",
    ".jfif": "image/pjpeg",
    ".jpe": "image/jpeg",
    ".jpeg": "image/jpeg",
    ".js": "application/x-javascript",
    ".lsx": "video/x-la-asf",
    ".latex": "application/x-latex",
    ".lsf": "video/x-la-asf",
    ".manifest": "application/x-ms-manifest",
    ".mhtml": "message/rfc822",
    ".mny": "application/x-msmoney",
    ".mht": "message/rfc822",
    ".mid": "audio/mid",
    ".mpv2": "video/mpeg",
    ".man": "application/x-troff-man",
    ".mvb": "application/x-msmediaview",
    ".mpeg": "video/mpeg",
    ".m3u": "audio/x-mpegurl",
    ".mdb": "application/x-msaccess",
    ".mpp": "application/vnd.ms-project",
    ".m1v": "video/mpeg",
    ".mpa": "video/mpeg",
    ".me": "application/x-troff-me",
    ".m13": "application/x-msmediaview",
    ".movie": "video/x-sgi-movie",
    ".m14": "application/x-msmediaview",
    ".mpe": "video/mpeg",
    ".mp2": "video/mpeg",
    ".mov": "video/quicktime",
    ".mp3": "audio/mpeg",
    ".mpg": "video/mpeg",
    ".ms": "application/x-troff-ms",
    ".nc": "application/x-netcdf",
    ".nws": "message/rfc822",
    ".oda": "application/oda",
    ".ods": "application/oleobject",
    ".pmc": "application/x-perfmon",
    ".p7r": "application/x-pkcs7-certreqresp",
    ".p7b": "application/x-pkcs7-certificates",
    ".p7s": "application/pkcs7-signature",
    ".pmw": "application/x-perfmon",
    ".ps": "application/postscript",
    ".p7c": "application/pkcs7-mime",
    ".pbm": "image/x-portable-bitmap",
    ".ppm": "image/x-portable-pixmap",
    ".pub": "application/x-mspublisher",
    ".pnm": "image/x-portable-anymap",
    ".png": "image/png",
    ".pml": "application/x-perfmon",
    ".p10": "application/pkcs10",
    ".pfx": "application/x-pkcs12",
    ".p12": "application/x-pkcs12",
    ".pdf": "application/pdf",
    ".pps": "application/vnd.ms-powerpoint",
    ".p7m": "application/pkcs7-mime",
    ".pko": "application/vndms-pkipko",
    ".ppt": "application/vnd.ms-powerpoint",
    ".pmr": "application/x-perfmon",
    ".pma": "application/x-perfmon",
    ".pot": "application/vnd.ms-powerpoint",
    ".prf": "application/pics-rules",
    ".pgm": "image/x-portable-graymap",
    ".qt": "video/quicktime",
    ".ra": "audio/x-pn-realaudio",
    ".rgb": "image/x-rgb",
    ".ram": "audio/x-pn-realaudio",
    ".rmi": "audio/mid",
    ".ras": "image/x-cmu-raster",
    ".roff": "application/x-troff",
    ".rtf": "application/rtf",
    ".rtx": "text/richtext",
    ".sv4crc": "application/x-sv4crc",
    ".spc": "application/x-pkcs7-certificates",
    ".setreg": "application/set-registration-initiation",
    ".snd": "audio/basic",
    ".stl": "application/vndms-pkistl",
    ".setpay": "application/set-payment-initiation",
    ".stm": "text/html",
    ".shar": "application/x-shar",
    ".sh": "application/x-sh",
    ".sit": "application/x-stuffit",
    ".spl": "application/futuresplash",
    ".sct": "text/scriptlet",
    ".scd": "application/x-msschedule",
    ".sst": "application/vndms-pkicertstore",
    ".src": "application/x-wais-source",
    ".sv4cpio": "application/x-sv4cpio",
    ".tex": "application/x-tex",
    ".tgz": "application/x-compressed",
    ".t": "application/x-troff",
    ".tar": "application/x-tar",
    ".tr": "application/x-troff",
    ".tif": "image/tiff",
    ".txt": "text/plain",
    ".texinfo": "application/x-texinfo",
    ".trm": "application/x-msterminal",
    ".tiff": "image/tiff",
    ".tcl": "application/x-tcl",
    ".texi": "application/x-texinfo",
    ".tsv": "text/tab-separated-values",
    ".ustar": "application/x-ustar",
    ".uls": "text/iuls",
    ".vcf": "text/x-vcard",
    ".wps": "application/vnd.ms-works",
    ".wav": "audio/wav",
    ".wrz": "x-world/x-vrml",
    ".wri": "application/x-mswrite",
    ".wks": "application/vnd.ms-works",
    ".wmf": "application/x-msmetafile",
    ".wcm": "application/vnd.ms-works",
    ".wrl": "x-world/x-vrml",
    ".wdb": "application/vnd.ms-works",
    ".wsdl": "text/xml",
    ".xap": "application/x-silverlight-app",
    ".xml": "text/xml",
    ".xlm": "application/vnd.ms-excel",
    ".xaf": "x-world/x-vrml",
    ".xla": "application/vnd.ms-excel",
    ".xls": "application/vnd.ms-excel",
    ".xof": "x-world/x-vrml",
    ".xlt": "application/vnd.ms-excel",
    ".xlc": "application/vnd.ms-excel",
    ".xsl": "text/xml",
    ".xbm": "image/x-xbitmap",
    ".xlw": "application/vnd.ms-excel",
    ".xpm": "image/x-xpixmap",
    ".xwd": "image/x-xwindowdump",
    ".xsd": "text/xml",
    ".z": "application/x-compress",
    ".zip": "application/x-zip-compressed",
    ".*": "application/octet-stream",
}

cnblog_upload/src/img/unload_img.py


import os
import re

from conf.conf import ST
from img.mime import mime_mapping
from server.cnblog_server import server


def find_md_img(md):
    """查找markdown中的图片,排除网络图片(不用上传)"""
    images = re.findall("!\\[.*?\\]\\((.*)\\)", md)
    images += re.findall('<img src="(.*?)"', md)
    images = [i for i in images if not re.match("((http(s?))|(ftp))://.*", i)]
    print(f'共找到{len(images)}张本地图片{images}')
    return images


async def upload_md_img(path):
    """上传图片"""
    name = os.path.basename(path)
    _, suffix = os.path.splitext(name)
    with open(path, 'rb') as f:
        file = {
            "bits": f.read(),
            "name": name,
            "type": mime_mapping[suffix]
        }
        url = server.metaWeblog.newMediaObject(ST.blog_id,ST.username ,ST.password, file)
        return url


def replace_md_img(path, img_mapping):
    """替换markdown中的图片链接"""
    with open(path, 'r', encoding='utf-8') as fr:
        md = fr.read()
        for local, net in img_mapping.items():  # 替换图片链接
            md = md.replace(local, net)
        if ST.img_format:
            md_links = re.findall("!\\[.*?\\]\\(.*?\\)", md)
            md_links += re.findall('<img src=.*/>', md)
            for ml in md_links:
                img_url = re.findall("!\\[.*?\\]\\((.*?)\\)", ml)
                img_url += re.findall('<img src="(.*?)"', ml)
                img_url = img_url[0]

                if  ST.img_format == "typora":
                    zoom = re.findall(r'style="zoom:(.*)%;"', ml)
                    if zoom:
                        md = md.replace(ml, f'<center><img src="{img_url}"  style="width:{zoom[0]}%;" /></center>')
                else:
                    md = md.replace(ml, ST.img_format.format(img_url))

        if ST.gen_network_file:
            path_net = os.path.join(os.path.dirname(path), '_network'.join(os.path.splitext(os.path.basename(path))))
            with open(path_net, 'w', encoding='utf-8') as fw:
                fw.write(md)
                print(f'图片链接替换完成,生成新markdown:{path_net}')
        return md

cnblog_upload/src/conf/conf.py


class ST:
    blog_url="https://rpc.cnblogs.com/metaweblog/xxxxx"
    blog_id="xxxxxxx"
    username="xxxxxxxxxxxxx"
    password="xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
    # 是否生成图片替换后本地文件,默认False关闭
    gen_network_file=False
    # 上传后是否发布,默认未发布,设置True为发布
    publish=True
    # 图片自定义显示格式,默认不设置
    img_format="typora"

标签:md,markdown,text,博客园,application,file,path,上传,image
From: https://www.cnblogs.com/zhuoss/p/17539474.html

相关文章

  • dotnet nuget的命令行上传(推送/发布)包到Nexus 3
    1、让VisualStudio在生成的时候也生成NuGet的包在项目上点右键,选“属性”,然后设置生成的时候制作NuGet的包。英文版在这里打勾:中文版在这里打勾:重新生成后,在bin\debug目录下,就能看到我们的包。2、去Nexus3服务器,查看仓库的URL从下图看到,我们在前面文章中,创建的名为study的NuGet......
  • 上传的文件需进行内容验证或者直接解析的例子
    特点就是:在form_valid验证中,完成数据的验证或者解析urls.pyfromdjango.urlsimportpathfrom.viewsimportUploadViewurlpatterns=[path('',UploadView.as_view(),name='index'),] forms.pyfromdjangoimportformsfromdjango.core.validat......
  • 常用的markdown的格式总结
    markdown格式<center>居中<center>;<divalign='center'>居中</div>实现文字居中。\tag{}公式编号。常用的markdown格式的链接https://blog.csdn.net/Annie_0321/article/details/115764983markdown花体字的写法。https://www.jianshu.com/p/d26dbcb26cc5ma......
  • Markdown基础语法_之_我啥也不会
    前提因为经常出现长时间不使用Markdown,经常忘记怎么使用,于是记录下我常用的基本语法,便于以后快速回忆。如果实在不理解请前往菜鸟教程。友情提示:减号和下划线区别。这是减号:-,这是下划线_。技巧一_标题使用字符“#”标记标题,“#”的数量表示几级标题。效果......
  • Typora 妙用+阿里云+Picgo上传--实现他人可以查看自己的博客
    Typora妙用+阿里云+Picgo上传关水水来源链接:大学生写博客,做笔记请你不要忘了Typora工具|带你从零开始认识和使用Typora_哔哩哔哩_bilibili如果还是不行可以根据此链接来排查自己的错误链接:Typora+PicGo+阿里云OSS实现图片上传_早上好我是DJ同学的博客-CSDN博客当时是无法在T......
  • 新建项目,上传到svn上。
    上传svn新项目。1、先把项目从svn上取出来,然后把本地的svn全部删除。2、把项目的名字变成自己想要的名字,还要把.project文件中的名字改成和项目一样的名字。3、把项目导入eclipse中4、然后点击team  -->> ShareProject,5、最后一步一步按提示操作。......
  • .net core 6.0 mvc js对文件分片上传文件+控制器合并文件保存
    js,通过ajax将文件分片提交  遇到问题:.netcore6.0mvc上传文件位置主文件夹下的\bin\Debug\net6.0 文件访问不了问题在startup配置#region让upload文件夹可以外部访问stringsUploadPath="/upload";stringsFDir=ToolsBasic.UsPath(sUploadPath);if(!Direc......
  • http 和 https区别,自动携带cookie的session对象,响应response,下载图片视频到本地,编码
    1.1自动携带cookie的session对象#session对象----》已经模拟登录上了一些网站---》单独把cookie取出来 -res.cookies-转成字典res.cookies.get_dict()#请求头和数据importrequestsheader={'Referer':'http://www.aa7a.cn/user.php?&ref=http%3A%2F%2......
  • 【开源分享】在线客服系统源码,支持发送文本表情,上传图片附件附详细搭建教程
    源码介绍golang开发的单用户在线客服系统,功能非常的简洁实用,没有多余的功能。golang语言可编译为二进制程序,自带守护进程功能,相比于流传最广的PHP客服系统要稳定环境配置服务器:linux或者windows都可以golang运行环境MySQLNginx配置Golang环境Windows系统首先下载golang......
  • 上传IPA后需要多久才能在构建版本中看到应用?
    上传IPA后需要多久才能在构建版本中看到应用?上架iOS应用时,上传IPA到构建版本和各种尺寸的iPhone截图制作是需要注意的两个重要步骤。但是这个过程相对比较繁琐,需要安装Xcode等相关软件和处理复杂的文件生成,给开发者们带来了不便。为了解决这个问题,我们推荐使用Appuploader工具......