• Typora编写markdown插入本地图片时自动上传图片到博客园


    Typora编写markdown插入图片时自动上传图片到博客园

    1.登录博客园后获取cookie值

    Cookie的key为`.Cnblogs.AspNetCore.Cookies`,仅此一个就足够了
    

    2.上脚本代码

    # upload_image2cnblogs.py
    # 支持本地图片及网络图片
    import re
    import requests
    import sys
    from pathlib import Path
    from uuid import uuid4
    
    
    ip_middle_octet = r"(?:.(?:1?d{1,2}|2[0-4]d|25[0-5]))"
    ip_last_octet = r"(?:.(?:0|[1-9]d?|1dd|2[0-4]d|25[0-5]))"
    
    regex = re.compile(  # noqa: W605
        r"^"
        # protocol identifier
        r"(?:(?:https?|ftp)://)"
        # user:pass authentication
        r"(?:[-a-zu00a1-uffff0-9._~%!$&'()*+,;=:]+"
        r"(?::[-a-z0-9._~%!$&'()*+,;=:]*)?@)?"
        r"(?:"
        r"(?P<private_ip>"
        # IP address exclusion
        # private & local networks
        r"(?:(?:10|127)" + ip_middle_octet + r"{2}" + ip_last_octet + r")|"
        r"(?:(?:169.254|192.168)" + ip_middle_octet + ip_last_octet + r")|"
        r"(?:172.(?:1[6-9]|2d|3[0-1])" + ip_middle_octet + ip_last_octet + r"))"
        r"|"
        # private & local hosts
        r"(?P<private_host>"
        r"(?:localhost))"
        r"|"
        # IP address dotted notation octets
        # excludes loopback network 0.0.0.0
        # excludes reserved space >= 224.0.0.0
        # excludes network & broadcast addresses
        # (first & last IP address of each class)
        r"(?P<public_ip>"
        r"(?:[1-9]d?|1dd|2[01]d|22[0-3])"
        r"" + ip_middle_octet + r"{2}"
        r"" + ip_last_octet + r")"
        r"|"
        # IPv6 RegEx from https://stackoverflow.com/a/17871737
        r"[("
        # 1:2:3:4:5:6:7:8
        r"([0-9a-fA-F]{1,4}:){7,7}[0-9a-fA-F]{1,4}|"
        # 1::                              1:2:3:4:5:6:7::
        r"([0-9a-fA-F]{1,4}:){1,7}:|"
        # 1::8             1:2:3:4:5:6::8  1:2:3:4:5:6::8
        r"([0-9a-fA-F]{1,4}:){1,6}:[0-9a-fA-F]{1,4}|"
        # 1::7:8           1:2:3:4:5::7:8  1:2:3:4:5::8
        r"([0-9a-fA-F]{1,4}:){1,5}(:[0-9a-fA-F]{1,4}){1,2}|"
        # 1::6:7:8         1:2:3:4::6:7:8  1:2:3:4::8
        r"([0-9a-fA-F]{1,4}:){1,4}(:[0-9a-fA-F]{1,4}){1,3}|"
        # 1::5:6:7:8       1:2:3::5:6:7:8  1:2:3::8
        r"([0-9a-fA-F]{1,4}:){1,3}(:[0-9a-fA-F]{1,4}){1,4}|"
        # 1::4:5:6:7:8     1:2::4:5:6:7:8  1:2::8
        r"([0-9a-fA-F]{1,4}:){1,2}(:[0-9a-fA-F]{1,4}){1,5}|"
        # 1::3:4:5:6:7:8   1::3:4:5:6:7:8  1::8
        r"[0-9a-fA-F]{1,4}:((:[0-9a-fA-F]{1,4}){1,6})|"
        # ::2:3:4:5:6:7:8  ::2:3:4:5:6:7:8 ::8       ::
        r":((:[0-9a-fA-F]{1,4}){1,7}|:)|"
        # fe80::7:8%eth0   fe80::7:8%1
        # (link-local IPv6 addresses with zone index)
        r"fe80:(:[0-9a-fA-F]{0,4}){0,4}%[0-9a-zA-Z]{1,}|"
        r"::(ffff(:0{1,4}){0,1}:){0,1}"
        r"((25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9]).){3,3}"
        # ::255.255.255.255   ::ffff:255.255.255.255  ::ffff:0:255.255.255.255
        # (IPv4-mapped IPv6 addresses and IPv4-translated addresses)
        r"(25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9])|"
        r"([0-9a-fA-F]{1,4}:){1,4}:"
        r"((25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9]).){3,3}"
        # 2001:db8:3:4::192.0.2.33  64:ff9b::192.0.2.33
        # (IPv4-Embedded IPv6 Address)
        r"(25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9])"
        r")]|"
        # host name
        r"(?:(?:(?:xn--)|[a-zu00a1-uffffU00010000-U0010ffff0-9]-?)*"
        r"[a-zu00a1-uffffU00010000-U0010ffff0-9]+)"
        # domain name
        r"(?:.(?:(?:xn--)|[a-zu00a1-uffffU00010000-U0010ffff0-9]-?)*"
        r"[a-zu00a1-uffffU00010000-U0010ffff0-9]+)*"
        # TLD identifier
        r"(?:.(?:(?:xn--[a-zu00a1-uffffU00010000-U0010ffff0-9]{2,})|"
        r"[a-zu00a1-uffffU00010000-U0010ffff]{2,}))"
        r")"
        # port number
        r"(?::d{2,5})?"
        # resource path
        r"(?:/[-a-zu00a1-uffffU00010000-U0010ffff0-9._~%!$&'()*+,;=:@/]*)?"
        # query string
        r"(?:?S*)?"
        # fragment
        r"(?:#S*)?"
        r"$",
        re.UNICODE | re.IGNORECASE
    )
    
    pattern = re.compile(regex)
    
    
    def is_url(value, public=False):
        result = pattern.match(value)
        if not public:
            return result
    
        return result and not any(
            (result.groupdict().get(key) for key in ('private_ip', 'private_host'))
        )
    
    
    argv = sys.argv
    if len(argv) <= 1:
        sys.exit(0)
    
    arg = sys.argv[1]
    
    if not is_url(arg):
        img_path = Path(arg)
        if not img_path.exists() or img_path.is_dir():
            sys.exit(0)
        else:
            img_name = img_path.name
            img_content = img_path.open('rb')
            content_type = f'image/{img_path.suffix[1:]}'
    else:
        res = requests.get(arg)
        content_type = res.headers['Content-Type']
        if 'image' in content_type:
            temp_list = arg.split('/')
            img_name = temp_list[-1] if temp_list else uuid4().hex
            img_content = res.content
        else:
            sys.exit(0)
    
    headers = {
        'x-mime-type': content_type,
    }
    
    cookies = {
        '.Cnblogs.AspNetCore.Cookies': 'Your Cookie',
    }
    
    upload_url = f"http://upload.cnblogs.com/imageuploader/processupload?host=www.cnblogs.com&qqfile={img_name}"
    
    
    img = {"qqfile": (img_name, img_content, content_type)}
    
    res = requests.post(upload_url, files=img, cookies=cookies, headers=headers)
    
    if res.status_code == 200:
        data = res.json()
        success = data['success']
        message = data['message']
        if success:
            print('Upload Success:')
            print(message)
    

    3.设置Typora

    自定义命令

    • 上传服务选择Custom Command

    • 命令为python(或其他虚拟环境python解释器路径) py脚本绝对路径,Typora会自动往脚本里传参图片的绝对路径,参数的长度和参数的个数都是不确定的

    • 图片上传完成后,Typora 需要你按指定格式在控制台输出图片的 URL 给它

      Upload Success:
      https://stormbuf.coding.net/p/piccoding/d/piccoding/git/raw/master/typora-icon2.png
      

      第一行一定要是 Upload Success:,然后第二个非空行开始,一行一个图片 URL

    • 插入图片时:这个选项可以选择上传图片或者选择无特殊操作

      • 选择上传图片时当你选择插入本地图片时会自动把图片上传到博客园并返回上传后的图片地址
      • 选择无特殊操作时,当你选择插入本地图片时会自动提示你进行其他操作,比如上传图片等
    • 上传图片时,如有报错,请仔细查看报错信息,如无明显报错信息,请检查Cookie是否已失效.

    4.总结

    当前脚本是上传图片到博客园做图床,目前只适用于当前博客园的上传图片接口,脚本是否过期,自行判断。此脚本只是做了个引子,读者照葫芦画瓢也可以上传其它OSS或者图床等。

  • 相关阅读:
    动态规划小练
    组合计数小练
    【WC2019】 通道
    【PKUSC2018】主斗地
    【NOI2009】诗人小G
    【THUWC 2017】随机二分图
    【NOI2017】游戏与2-sat方案输出
    Codeforces 1109D sasha and interesting fact from graph theory
    Codeforces 1152E neko and flashback
    ZJOI2019游记
  • 原文地址:https://www.cnblogs.com/zepc007/p/14749300.html
Copyright © 2020-2023  润新知