怪物奇妙物语

宇宙无敌超级美少男的怪物奇妙物语

首页 新随笔 联系 管理

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"
posted on 2023-07-09 21:38  超级无敌美少男战士  阅读(43)  评论(0编辑  收藏  举报