CSDN 自动上传图片并优化Markdown的图片显示

news2024/10/6 22:24:26

文章目录

    • 完整代码
    • 一、上传资源
    • 二、替换 MD 中的引用文件为在线链接
    • 参考

完整代码

完整代码由两个文件组成,upload.pymain.py,放在同一目录下运行 main.py 就好!

# upload.py
import requests  


class UploadPic:  
    def __init__(self, cookie):  
        self.cookie = cookie  
  
        # 解析  
        self.file_path = ''  
        self.img_type = ''  
  
        # 两个请求体  
        self.upload_data = {}  
        self.csdn_data = {}  
        self.output_url = ''  
  
    def _get_file(self, file_path):  
        with open(file_path, mode='rb') as f:  
            binary_data = f.read()  
        return binary_data  
  
    def _upload_request(self):  
        headers = {  
            'accept': '*/*',  
            'accept-language': 'zh-CN,zh;q=0.9,en;q=0.8,en-GB;q=0.7,en-US;q=0.6',  
            'content-type': 'application/json',  
            'cookie': self.cookie,  
            'origin': 'https://editor.csdn.net',  
            'priority': 'u=1, i',  
            'referer': 'https://editor.csdn.net/',  
            'sec-ch-ua': '"Not/A)Brand";v="8", "Chromium";v="126", "Microsoft Edge";v="126"',  
            'sec-ch-ua-mobile': '?0',  
            'sec-ch-ua-platform': '"Windows"',  
            'sec-fetch-dest': 'empty',  
            'sec-fetch-mode': 'cors',  
            'sec-fetch-site': 'same-site',  
            'user-agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/126.0.0.0 Safari/537.36 Edg/126.0.0.0',  
        }  
  
        params = {  
            'type': 'blog',  
            'rtype': 'markdown',  
            'x-image-template': '',  
            'x-image-app': 'direct_blog',  
            'x-image-dir': 'direct',  
            'x-image-suffix': self.img_type,  
        }  
  
        url = 'https://imgservice.csdn.net/direct/v1.0/image/upload'  
  
        response = requests.get(url, params=params, headers=headers)  
        try:  
            self.upload_data = response.json()  
        except Exception as e:  
            return e  
  
    def _csdn_request(self):  
        headers = {  
            'Accept': 'application/json, text/javascript, */*; q=0.01',  
            'Accept-Language': 'zh-CN,zh;q=0.9,en;q=0.8,en-GB;q=0.7,en-US;q=0.6',  
            'Connection': 'keep-alive',  
            'Origin': 'https://editor.csdn.net',  
            'Referer': 'https://editor.csdn.net/',  
            'Sec-Fetch-Dest': 'empty',  
            'Sec-Fetch-Mode': 'cors',  
            'Sec-Fetch-Site': 'cross-site',  
            'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/126.0.0.0 Safari/537.36 Edg/126.0.0.0',  
            'sec-ch-ua': '"Not/A)Brand";v="8", "Chromium";v="126", "Microsoft Edge";v="126"',  
            'sec-ch-ua-mobile': '?0',  
            'sec-ch-ua-platform': '"Windows"',  
        }  
  
        files = {  
            'key': (None, self.upload_data['data']['filePath']),  
            'policy': (None, self.upload_data['data']['policy']),  
            'OSSAccessKeyId': (None, self.upload_data['data']['accessId']),  
            'success_action_status': (None, '200'),  
            'signature': (None, self.upload_data['data']['signature']),  
            'callback': (None, self.upload_data['data']['callbackUrl']),  
            'file': (f'image.{self.img_type}', self._get_file(self.file_path), f'image/{self.img_type}'),  
        }  
  
        url = 'https://csdn-img-blog.oss-cn-beijing.aliyuncs.com/'  
  
        response = requests.post(url, headers=headers, files=files)  
        try:  
            self.csdn_data = response.json()  
            self.output_url = self.csdn_data['data']['imageUrl']  
        except Exception as e:  
            return e  
  
    def upload_image(self, file_path):  
        self.file_path = file_path  
        self.img_type = self.file_path.split('.')[-1]  
  
        exception_1 = self._upload_request()  
        assert exception_1 is None, exception_1  
        exception_2 = self._csdn_request()  
        assert exception_2 is None, exception_2  
  
        return self.output_url  
  
  
if __name__ == '__main__':  
    cookie = '' # 输入你的cookie  
    upload = UploadPic(cookie)  
    output_url = upload.upload_image('')  #输入你需要上传的文件位置
    print(output_url)
# main.py
import os  
import re  
from pathlib import Path  
from rich.progress import track  
from upload import UploadPic  


class CSDNTransform:  
    def __init__(self, upload:UploadPic, file_path, walk_path='C:/Users/Administrator/Documents/Obsidian Vault/'):  
        self.upload = upload  
        self.file_path = file_path  
        self.walk_path = walk_path  
  
        self.markdown_text = ''  
        self.image_lst = []  
        self.posterior_image_lst = []  
        self.image_2_url_dic = {}  
  
    def _get_markdown_text(self):  
        with open(self.file_path, mode='r', encoding='utf-8') as f:  
            markdown_text = f.read()  
        self.markdown_text = markdown_text  
  
    def _process_markdown_text(self):  
        image_lst = re.findall(r'(!\[\[.*]])', self.markdown_text)  
        posterior_image_lst = [item[3:-2] for item in image_lst]  
  
        self.image_lst = image_lst  
        self.posterior_image_lst = posterior_image_lst  
  
    def _get_target_image_path(self, target_path):  
        for root, floders, files in os.walk(self.walk_path):  
            for file in files:  
                if file == target_path:  
                    return str(Path(root) / file)  
  
    def _get_the_url_of_image(self, image_path):  
        image_url = self.upload.upload_image(image_path)  
        return image_url  
  
    def get_the_urls(self):  
        self._get_markdown_text()  
        self._process_markdown_text()  
  
        not_exist_image_index = []  
  
        for ix, (origin_image, target_path) in track(enumerate(zip(self.image_lst, self.posterior_image_lst))):  
            image_path = self._get_target_image_path(target_path)  
            if image_path is not None:  
                image_url = self._get_the_url_of_image(image_path)  
                self.image_2_url_dic[origin_image] = image_url  
            else:  
                not_exist_image_index.append(ix)  
  
        # 清楚掉需要删除的index  
        num = 0  
        for ix in not_exist_image_index:  
            del self.image_lst[ix-num]  
            del self.posterior_image_lst[ix-num]  
            num += 1  
  
    def _the_transform_data_from(self, image_url):  
        data_form = f"""\n<div align=center><img src="{image_url}"></div>\n"""  
        return data_form  
  
    def _save_markdown_text(self, output_file='markdown_processed.txt'):  
        with open(output_file, mode='w', encoding='utf-8') as f:  
            f.write(self.markdown_text)  
  
    def get_transform(self):  
        self.get_the_urls()  
  
        # Judge the length  
        assert len(self.image_lst) == len(self.image_2_url_dic), f"上传成功{len(self.image_2_url_dic)}张图片,总共有{len(self.image_lst)}张图片"  
  
        for origin_image, image_url in self.image_2_url_dic.items():  
            self.markdown_text = self.markdown_text.replace(origin_image, self._the_transform_data_from(image_url))  
  
        self._save_markdown_text()


if __name__ == '__main__':  
    cookie = ''  # 输入你的cookie
    file_path = ''  # 输入你要转换的markdown文件地址
    upload = UploadPic(cookie)  
    transform = CSDNTransform(upload, file_path)  
    markdown_text = transform.get_transform()

	# 修改后的 Markdown 在当前目录的 markdown_processed.txt 文件中

一、上传资源

首先我们解析 CSDN 上传请求,这里随便上传一张图片,观察请求;

请求由三部分组成,分别是:1. 获取存储位置和签名验证信息;2. 利用签名等验证信息上传文件;3. 获取文件信息并显示;

仔细观察两个请求,upload 请求是 GET ,csdn 请求是 POST,其结果很明显 csdn 请求是主体,仔细观察 csdn 的参数,可以所有参数都可以利用 upload 的返回结果得到;

那么接下来我们开始构造 upload 请求

import requests

headers = {
    'accept': '*/*',
    'accept-language': 'zh-CN,zh;q=0.9,en;q=0.8,en-GB;q=0.7,en-US;q=0.6',
    'content-type': 'application/json',
    'cookie': '', # 输入自己的cookies
    'origin': 'https://editor.csdn.net',
    'priority': 'u=1, i',
    'referer': 'https://editor.csdn.net/',
    'sec-ch-ua': '"Not/A)Brand";v="8", "Chromium";v="126", "Microsoft Edge";v="126"',
    'sec-ch-ua-mobile': '?0',
    'sec-ch-ua-platform': '"Windows"',
    'sec-fetch-dest': 'empty',
    'sec-fetch-mode': 'cors',
    'sec-fetch-site': 'same-site',
    'user-agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/126.0.0.0 Safari/537.36 Edg/126.0.0.0',
}

params = {
    'type': 'blog',
    'rtype': 'markdown',
    'x-image-template': '',
    'x-image-app': 'direct_blog',
    'x-image-dir': 'direct',
    'x-image-suffix': 'png',
}

url = 'https://imgservice.csdn.net/direct/v1.0/image/upload'
response = requests.get(url, params=params, headers=headers)

# 获得数据
upload_data = response.json()

得到 json 内容如下,通过比较该内容下 expire 和 time 库下的 time.time() * 1000,再根据英文名可以推断,expire 表示的是上传文件这一请求的失效时间,即 csdn 请求的最晚成功时间;

{'code': 200,
 'data': {'accessId': 'LTAI5tK31AXMAqwzaX1wn4hH',
          'callbackUrl': 'eyJjYWxsYmFja0JvZHlUeXBlIjoiYXBwbGljYXRpb24vanNvbiIsImNhbGxiYWNrVXJsIjoiaHR0cHM6Ly9pbWdzZXJ2aWNlLmNzZG4ubmV0L2RpcmVjdC92MS4wL2ltYWdlL2NhbGxiYWNrIiwiY2FsbGJhY2tCb2R5Ijoie1wiZmlsZVBhdGhcIjpcImRpcmVjdC9jN2VlYWNjZjU2ZDM0MzM3OWQ2Yjk4ZmYwNGYyZWFjNS5wbmdcIixcImlzQXVkaXRcIjoxLFwieC1pbWFnZS1hcHBcIjpcImRpcmVjdF9ibG9nXCIsXCJ0eXBlXCI6XCJibG9nXCIsXCJ1cmxNZDVcIjpcImM3ZWVhY2NmNTZkMzQzMzc5ZDZiOThmZjA0ZjJlYWM1XCIsXCJydHlwZVwiOlwibWFya2Rvd25cIixcImhvc3RuYW1lXCI6XCJodHRwczovL2ltZy1ibG9nLmNzZG5pbWcuY24vXCIsXCJzaXplXCI6XCIke3NpemV9XCIsXCJ4LWltYWdlLWRpclwiOlwiZGlyZWN0XCIsXCJ3aWR0aFwiOlwiJHtpbWFnZUluZm8ud2lkdGh9XCIsXCJ4LWltYWdlLXN1ZmZpeFwiOlwicG5nXCIsXCJ1c2VybmFtZVwiOlwibTBfNzI5NDczOTBcIixcImhlaWdodFwiOlwiJHtpbWFnZUluZm8uaGVpZ2h0fVwifSJ9',
          'dir': 'direct',
          'expire': '1718611892700',
          'filePath': 'direct/c7eeaccf56d343379d6b98ff04f2eac5.png',
          'host': 'https://csdn-img-blog.oss-cn-beijing.aliyuncs.com',
          'policy': 'eyJleHBpcmF0aW9uIjoiMjAyNC0wNi0xN1QwODoxMTozMi43MDBaIiwiY29uZGl0aW9ucyI6W1siY29udGVudC1sZW5ndGgtcmFuZ2UiLDAsMTA0ODU3NjAwXSxbInN0YXJ0cy13aXRoIiwiJGtleSIsImRpcmVjdC9jN2VlYWNjZjU2ZDM0MzM3OWQ2Yjk4ZmYwNGYyZWFjNS5wbmciXV19',
          'signature': '2hRKp5YO3epBJe5+Qt7Ngi7P/y4='},
 'message': None,
 'msg': 'success'}

下面利用 upload 得到的请求来构造 csdn 请求;

import requests
from requests_toolbelt.multipart.encoder import MultipartEncoder

def get_file(file_path):
	"""获取文件的二进制数据"""
    with open(file_path, mode='rb') as f:
        binary_data = f.read()
    return binary_data

headers = {
    'Accept': 'application/json, text/javascript, */*; q=0.01',
    'Accept-Language': 'zh-CN,zh;q=0.9,en;q=0.8,en-GB;q=0.7,en-US;q=0.6',
    'Connection': 'keep-alive',
    'Origin': 'https://editor.csdn.net',
    'Referer': 'https://editor.csdn.net/',
    'Sec-Fetch-Dest': 'empty',
    'Sec-Fetch-Mode': 'cors',
    'Sec-Fetch-Site': 'cross-site',
    'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/126.0.0.0 Safari/537.36 Edg/126.0.0.0',
    'sec-ch-ua': '"Not/A)Brand";v="8", "Chromium";v="126", "Microsoft Edge";v="126"',
    'sec-ch-ua-mobile': '?0',
    'sec-ch-ua-platform': '"Windows"',
}

success_action_status = '200'

# upload 请求中获取到的数据
key = upload_data['data']['filePath']
policy = upload_data['data']['policy']
OSSAccessKeyId = upload_data['data']['accessId']
signature = upload_data['data']['signature']
callback = upload_data['data']['callbackUrl']

# 上传的图片位置,
file = get_file('') # 输入需要上传文件的位置

files = {
    'key': (None, key),
    'policy': (None, policy),
    'OSSAccessKeyId': (None, OSSAccessKeyId),
    'success_action_status': (None, '200'),
    'signature': (None, signature),
    'callback': (None, callback),
    'file': ('image.png', file, 'image/png'),
}

url = 'https://csdn-img-blog.oss-cn-beijing.aliyuncs.com/'
response = requests.post(url, headers=headers, files=files)

print(response.text)

得到 Json 数据如下

{'code': 200,
 'data': {'hostname': 'https://img-blog.csdnimg.cn/',
  'imageUrl': 'https://img-blog.csdnimg.cn/direct/97c5610606c140afb474800403140ea3.png',
  'width': '1138',
  'targetObjectKey': 'direct/97c5610606c140afb474800403140ea3.png',
  'x-image-suffix': 'png',
  'height': '239'},
 'msg': 'success'}

在其中 imageUrl 就表示上传的图片地址,同时,图片格式有许多种,面对不同的图片格式,在尝试观察后发现只需要修改 upload 请求中 parms 中的 x-image-suffixcsdn 请求中 files 中的 file

整合得到完整上传类如下:

import requests  
  
  
class UploadPic:  
    def __init__(self, cookie):  
        self.cookie = cookie  
  
        # 解析  
        self.file_path = ''  
        self.img_type = ''  
  
        # 两个请求体  
        self.upload_data = {}  
        self.csdn_data = {}  
        self.output_url = ''  
  
    def _get_file(self, file_path):  
        with open(file_path, mode='rb') as f:  
            binary_data = f.read()  
        return binary_data  
  
    def _upload_request(self):  
        headers = {  
            'accept': '*/*',  
            'accept-language': 'zh-CN,zh;q=0.9,en;q=0.8,en-GB;q=0.7,en-US;q=0.6',  
            'content-type': 'application/json',  
            'cookie': self.cookie,  
            'origin': 'https://editor.csdn.net',  
            'priority': 'u=1, i',  
            'referer': 'https://editor.csdn.net/',  
            'sec-ch-ua': '"Not/A)Brand";v="8", "Chromium";v="126", "Microsoft Edge";v="126"',  
            'sec-ch-ua-mobile': '?0',  
            'sec-ch-ua-platform': '"Windows"',  
            'sec-fetch-dest': 'empty',  
            'sec-fetch-mode': 'cors',  
            'sec-fetch-site': 'same-site',  
            'user-agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/126.0.0.0 Safari/537.36 Edg/126.0.0.0',  
        }  
  
        params = {  
            'type': 'blog',  
            'rtype': 'markdown',  
            'x-image-template': '',  
            'x-image-app': 'direct_blog',  
            'x-image-dir': 'direct',  
            'x-image-suffix': self.img_type,  
        }  
  
        url = 'https://imgservice.csdn.net/direct/v1.0/image/upload'  
  
        response = requests.get(url, params=params, headers=headers)  
        try:  
            self.upload_data = response.json()  
        except Exception as e:  
            return e  
  
    def _csdn_request(self):  
        headers = {  
            'Accept': 'application/json, text/javascript, */*; q=0.01',  
            'Accept-Language': 'zh-CN,zh;q=0.9,en;q=0.8,en-GB;q=0.7,en-US;q=0.6',  
            'Connection': 'keep-alive',  
            'Origin': 'https://editor.csdn.net',  
            'Referer': 'https://editor.csdn.net/',  
            'Sec-Fetch-Dest': 'empty',  
            'Sec-Fetch-Mode': 'cors',  
            'Sec-Fetch-Site': 'cross-site',  
            'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/126.0.0.0 Safari/537.36 Edg/126.0.0.0',  
            'sec-ch-ua': '"Not/A)Brand";v="8", "Chromium";v="126", "Microsoft Edge";v="126"',  
            'sec-ch-ua-mobile': '?0',  
            'sec-ch-ua-platform': '"Windows"',  
        }  
  
        files = {  
            'key': (None, self.upload_data['data']['filePath']),  
            'policy': (None, self.upload_data['data']['policy']),  
            'OSSAccessKeyId': (None, self.upload_data['data']['accessId']),  
            'success_action_status': (None, '200'),  
            'signature': (None, self.upload_data['data']['signature']),  
            'callback': (None, self.upload_data['data']['callbackUrl']),  
            'file': (f'image.{self.img_type}', self._get_file(self.file_path), f'image/{self.img_type}'),  
        }  
  
        url = 'https://csdn-img-blog.oss-cn-beijing.aliyuncs.com/'  
  
        response = requests.post(url, headers=headers, files=files)  
        try:  
            self.csdn_data = response.json()  
            self.output_url = self.csdn_data['data']['imageUrl']  
        except Exception as e:  
            return e  
  
    def upload_image(self, file_path):  
        self.file_path = file_path  
        self.img_type = self.file_path.split('.')[-1]  
  
        exception_1 = self._upload_request()  
        assert exception_1 is None, exception_1  
        exception_2 = self._csdn_request()  
        assert exception_2 is None, exception_2  
  
        return self.output_url  
  
  
if __name__ == '__main__':  
    cookie = '' # 输入你的cookie  
    upload = UploadPic(cookie)  
    output_url = upload.upload_image('')  #输入你需要上传的文件位置
    print(output_url)

二、替换 MD 中的引用文件为在线链接

首先,肯定是整体替换而不是单个替换,因此我们的流程为:1. 上传所有文件,直到所有的文件都上传成功;2. 替换所有文件;

首先提取出 Markdown 中所有的图片信息,一般来说图片信息都在两个中括号之间 ![[ img_pic ]],使用 re 正则提取,代码如下;

import re

file_path = 'C:/Users/Administrator/Documents/Obsidian Vault/UE开发/My FirstGame Tutorial.md'

with open(file_path, mode='r', encoding='utf-8') as f:
    markdown_text = f.read()

image_lst = re.findall(r'(!\[\[.*\]\])', markdown_text)
posterior_image_lst = [item[3:-2] for item in image_lst]

提取出所有的 img_pic 后,我们需要在根目录下寻找文件,一般来说在 Markdown 中文件名是不重复的;

import os
from pathlib import Path

def get_target_image_path(target_path):
    walk_path = 'C:/Users/Administrator/Documents/Obsidian Vault/'
    for root, floders, files in os.walk(walk_path):
        for file in files:
            if file == target_path:
                return Path(root) / file

get_target_image_path(posterior_image_lst[0])

获取到了绝对位置后,我们可以将图片上传,在检查图片全部都上传完毕后,我们就可以替换 ![[ img_pic ]]

import os  
import re  
import requests  
from pathlib import Path  
from rich.progress import track  
  
  
class UploadPic:  
    def __init__(self, cookie):  
        self.cookie = cookie  
  
        # 解析  
        self.file_path = ''  
        self.img_type = ''  
  
        # 两个请求体  
        self.upload_data = {}  
        self.csdn_data = {}  
        self.output_url = ''  
  
    def _get_file(self, file_path):  
        with open(file_path, mode='rb') as f:  
            binary_data = f.read()  
        return binary_data  
  
    def _upload_request(self):  
        headers = {  
            'accept': '*/*',  
            'accept-language': 'zh-CN,zh;q=0.9,en;q=0.8,en-GB;q=0.7,en-US;q=0.6',  
            'content-type': 'application/json',  
            'cookie': self.cookie,  
            'origin': 'https://editor.csdn.net',  
            'priority': 'u=1, i',  
            'referer': 'https://editor.csdn.net/',  
            'sec-ch-ua': '"Not/A)Brand";v="8", "Chromium";v="126", "Microsoft Edge";v="126"',  
            'sec-ch-ua-mobile': '?0',  
            'sec-ch-ua-platform': '"Windows"',  
            'sec-fetch-dest': 'empty',  
            'sec-fetch-mode': 'cors',  
            'sec-fetch-site': 'same-site',  
            'user-agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/126.0.0.0 Safari/537.36 Edg/126.0.0.0',  
        }  
  
        params = {  
            'type': 'blog',  
            'rtype': 'markdown',  
            'x-image-template': '',  
            'x-image-app': 'direct_blog',  
            'x-image-dir': 'direct',  
            'x-image-suffix': self.img_type,  
        }  
  
        url = 'https://imgservice.csdn.net/direct/v1.0/image/upload'  
  
        response = requests.get(url, params=params, headers=headers)  
        try:  
            self.upload_data = response.json()  
        except Exception as e:  
            return e  
  
    def _csdn_request(self):  
        headers = {  
            'Accept': 'application/json, text/javascript, */*; q=0.01',  
            'Accept-Language': 'zh-CN,zh;q=0.9,en;q=0.8,en-GB;q=0.7,en-US;q=0.6',  
            'Connection': 'keep-alive',  
            'Origin': 'https://editor.csdn.net',  
            'Referer': 'https://editor.csdn.net/',  
            'Sec-Fetch-Dest': 'empty',  
            'Sec-Fetch-Mode': 'cors',  
            'Sec-Fetch-Site': 'cross-site',  
            'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/126.0.0.0 Safari/537.36 Edg/126.0.0.0',  
            'sec-ch-ua': '"Not/A)Brand";v="8", "Chromium";v="126", "Microsoft Edge";v="126"',  
            'sec-ch-ua-mobile': '?0',  
            'sec-ch-ua-platform': '"Windows"',  
        }  
  
        files = {  
            'key': (None, self.upload_data['data']['filePath']),  
            'policy': (None, self.upload_data['data']['policy']),  
            'OSSAccessKeyId': (None, self.upload_data['data']['accessId']),  
            'success_action_status': (None, '200'),  
            'signature': (None, self.upload_data['data']['signature']),  
            'callback': (None, self.upload_data['data']['callbackUrl']),  
            'file': (f'image.{self.img_type}', self._get_file(self.file_path), f'image/{self.img_type}'),  
        }  
  
        url = 'https://csdn-img-blog.oss-cn-beijing.aliyuncs.com/'  
  
        response = requests.post(url, headers=headers, files=files)  
        try:  
            self.csdn_data = response.json()  
            self.output_url = self.csdn_data['data']['imageUrl']  
        except Exception as e:  
            return e  
  
    def upload_image(self, file_path):  
        self.file_path = file_path  
        self.img_type = self.file_path.split('.')[-1]  
  
        exception_1 = self._upload_request()  
        assert exception_1 is None, exception_1  
        exception_2 = self._csdn_request()  
        assert exception_2 is None, exception_2  
  
        return self.output_url  
  
  
class CSDNTransform:  
    def __init__(self, upload:UploadPic, file_path, walk_path='C:/Users/Administrator/Documents/Obsidian Vault/'):  
        self.upload = upload  
        self.file_path = file_path  
        self.walk_path = walk_path  
  
        self.markdown_text = ''  
        self.image_lst = []  
        self.posterior_image_lst = []  
        self.image_2_url_dic = {}  
  
    def _get_markdown_text(self):  
        with open(self.file_path, mode='r', encoding='utf-8') as f:  
            markdown_text = f.read()  
        self.markdown_text = markdown_text  
  
    def _process_markdown_text(self):  
        image_lst = re.findall(r'(!\[\[.*]])', self.markdown_text)  
        posterior_image_lst = [item[3:-2] for item in image_lst]  
  
        self.image_lst = image_lst  
        self.posterior_image_lst = posterior_image_lst  
  
    def _get_target_image_path(self, target_path):  
        for root, floders, files in os.walk(self.walk_path):  
            for file in files:  
                if file == target_path:  
                    return str(Path(root) / file)  
  
    def _get_the_url_of_image(self, image_path):  
        image_url = self.upload.upload_image(image_path)  
        return image_url  
  
    def get_the_urls(self):  
        self._get_markdown_text()  
        self._process_markdown_text()  
  
        not_exist_image_index = []  
  
        for ix, (origin_image, target_path) in track(enumerate(zip(self.image_lst, self.posterior_image_lst))):  
            image_path = self._get_target_image_path(target_path)  
            if image_path is not None:  
                image_url = self._get_the_url_of_image(image_path)  
                self.image_2_url_dic[origin_image] = image_url  
            else:  
                not_exist_image_index.append(ix)  
  
        # 清楚掉需要删除的index  
        num = 0  
        for ix in not_exist_image_index:  
            del self.image_lst[ix-num]  
            del self.posterior_image_lst[ix-num]  
            num += 1  
  
    def _the_transform_data_from(self, image_url):  
        data_form = f"""\n<div align=center><img src="{image_url}"></div>\n"""  
        return data_form  
  
    def _save_markdown_text(self, output_file='markdown_processed.txt'):  
        with open(output_file, mode='w', encoding='utf-8') as f:  
            f.write(self.markdown_text)  
  
    def get_transform(self):  
        self.get_the_urls()  
  
        # Judge the length  
        assert len(self.image_lst) == len(self.image_2_url_dic), f"上传成功{len(self.image_2_url_dic)}张图片,总共有{len(self.image_lst)}张图片"  
  
        for origin_image, image_url in self.image_2_url_dic.items():  
            self.markdown_text = self.markdown_text.replace(origin_image, self._the_transform_data_from(image_url))  
  
        self._save_markdown_text()
  
if __name__ == '__main__':  
    cookie = ''  # 输入你的cookie
    file_path = ''  # 输入你要转换的markdown文件地址
    upload = UploadPic(cookie)  
    transform = CSDNTransform(upload, file_path)  
    markdown_text = transform.get_transform()

	# 修改后的 Markdown 在当前目录的 markdown_processed.txt 文件中

参考

requests库post请求参数data、json和files的使用_requests post data-CSDN博客
HTTP协议之multipart/form-data请求分析_http form-data请求-CSDN博客

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1834312.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

SpringSecurity6从入门到实战之自定义登录页面

SpringSecurity6从入门到实战之自定义登录页面 在使用SpringSecurity进行认证操作的时候,可以发现默认提供的登录页面比较简陋.那么我们能否对登录页面进行自定义配置呢?接下来开始讲解应该如何进行配置 自定义登录页面流程 引入模板依赖 由于自定义登录页面会使用到前端相关…

树与图的深度优先遍历——AcWing.846树的重心

树与图的深度优先遍历 定义 从图的某个顶点出发&#xff0c;沿着一条路径尽可能深地访问图中顶点。 运用情况 图的连通性判断。寻找特定路径或回路。 注意事项 要标记已访问的节点&#xff0c;以避免重复访问导致死循环。对于有向图和无向图可能需要不同的处理。 解题思…

mysql数据库中触发器的使用

一、修改分隔符号 delimiter $$或者是//或者~~都行 二、创建触发器函数名称 create trigger 函数名 三、什么样的操作出发&#xff0c;操作那个表 after&#xff1a;.....之后触发 befor&#xff1a;.....之前触发 insert&#xff1a; 插入触发 update&#xff1a;修改被触发 d…

鸿蒙APP开发的技术难点

鸿蒙APP开发的技术难点主要体现在以下几个方面&#xff0c;鸿蒙APP开发是一项技术难度较高的工作&#xff0c;需要开发者具备扎实的编程基础、分布式开发能力和学习新技术的意愿。北京木奇移动技术有限公司&#xff0c;专业的软件外包开发公司&#xff0c;欢迎交流合作。 1. 多…

充电宝什么牌子好?买多少毫安充电宝合适?这几个误区别踩!

在选择充电宝时&#xff0c;很多消费者常常被各种品牌和容量规格搞得眼花缭乱。不少人认为&#xff0c;容量越大越好&#xff0c;但事实并非如此。其实&#xff0c;根据日常使用需求&#xff0c;选择10000毫安的充电宝已经足够应对大多数情况。10000毫安的充电宝不仅能够满足手…

css-padding

文章目录 paddingpadding与元素的尺寸对于block块状水平元素复杂关系影响元素尺寸不影响元素尺寸最小宽度显示 关系总结 对于inline内联水平元素复杂关系水平padding影响尺寸垂直padding影响背景色区域 padding负值和百分比值负值百分比值inline水平元素的padding的百分比值空i…

WPF 深入理解三、控件结构

控件结构 演示&#xff1a; 思考疑问 为什么有一些元素是Content显示内容,而一些元素是Text显示内容? 凡是继承于Contentcontrol的控件,他们的定义内容用Content&#xff0c;除了TextBlock使用的是Text,大部分都是Content设置其显示内容。 为什么有一些元素有Padding,而一些元…

铁砧帝国延迟高?铁砧帝国延迟严重这样解决

铁砧帝国是一款少见的多人在线游戏&#xff0c;游戏能支持上千名玩家建立帝国并互相作战。而且这款游戏在细节方面也做足准备&#xff0c;设计了攻城梯和攻城锤等设备&#xff0c;以攻破坚固的城墙和要塞&#xff0c;不过具体获取方法就需要玩家自己摸索。因为最近开放了测试申…

Vue3基础介绍

文章目录 一、简介1、简介2、性能提升3、源码升级4、拥抱TypeScript5、新特性 二、创建Vue3.0工程1、使用vue-cli创建2、使用vite创建 三、分析工程结构1、main.js2、组件中 一、简介 1、简介 2020年9月18日&#xff0c;Vue.js发布3.0版本&#xff0c;代号(One Piece)海贼王 …

K8sGPT+Ollama:免费的 Kubernetes 自动化诊断方案

周末检查博客草稿&#xff0c;发现了这篇。记得当时是与 Kubernetes 自动化诊断工具&#xff1a;k8sgpt-operator 一起写的&#xff0c;算算过去了一年之久&#xff0c;这拖延症也算是病入膏肓了。原本想使用 K8sGPT LocalAI 的方案&#xff0c;由于之前试过 Ollama&#xff0…

OpenMMlab AI实战营第五、六期培训

OpenMMlab AI实战营第五、六期培训 OpenMMlab实战营第五、六次课2023.2.7-9学习参考第五次课笔记第六次课笔记一、什么是语义分割二、语义分割 v.s. 实例分割 v.s. 全景分割三、语义分割经典模型1.语义分割的基本思路2.**复用卷积计算**3.全连接层的卷积化4.预测图的升采样5.双…

Stable Diffusion 3 Medium 正式开源,用户对此产品评价如何?

前两天 Stability.AI 终于开源了 Stable Diffusion 3&#xff0c;虽然只是中杯的 Medium 版本&#xff0c;没有放出当初宣布的 8B 版本[1]&#xff0c;但也在很多方面取得了进步。本想第一时间尝鲜测试&#xff0c;但这几天出差在外&#xff0c;使用颇不方便。 正好老朋友揽睿…

HTTP/3 协议学习

前一篇&#xff1a; HTTP/2 协议学习-CSDN博客 HTTP/3 协议介绍 HTTP/3 是互联网上用于传输超文本的协议 HTTP 的第三个主要版本。它是 HTTP/2 的后继者&#xff0c;旨在进一步提高网络性能和安全性。HTTP/3 与前两个版本的主要区别在于它使用了一个完全不同的底层传输协议—…

安泰电压放大器的选型原则是什么

电压放大器是电子电路中常用的一种器件&#xff0c;主要用于放大输入电压信号。在选型电压放大器时&#xff0c;需要考虑以下几个原则。 根据应用需求确定放大倍数。放大倍数是指输出电压与输入电压之间的倍数关系&#xff0c;也称为增益。不同的应用场景对放大倍数的要求不同&…

3个火火火的AI项目,开源了!

友友们&#xff0c;今天我要给你们安利三个超酷的开源项目&#xff0c;它们都和AI有关&#xff0c;而且每一个都能让你的日常生活变得更加有趣和便捷&#xff01;(最近AI绘图又又超神了&#xff0c;分享以下美图养眼) 01 字节出品&#xff0c;文字转语音Seed-TTS 字节推出了一…

Ubuntu,Centos,Linux服务器安装Mellanox MCX653105A IB网卡HCA卡驱动

Mellanox 官方驱动下载地址 https://network.nvidia.com/products/infiniband-drivers/linux/mlnx_ofed/ 选择对应操作系统 官方链接速度比较慢&#xff0c;推荐个友商的下载地址 https://support.xfusion.com/support/#/zh/rack-servers/2288h-v5-pid-21872244/software …

【算法专题--链表】K个一组翻转链表 -- 高频面试题(图文详解,小白一看就懂!!!)

目录 一、前言 二、题目描述 三、解题方法 ⭐双指针 -- 采用哨兵位头节点 &#x1f95d; 什么是哨兵位头节点&#xff1f; &#x1f34d; 案例图解 四、总结与提炼 五、共勉 一、前言 K个一组翻转链表 这道题&#xff0c;可以说是--链表专题--&#xff0c;最经典…

Java内存模型(JMM)详解

文章目录 1、Java内存模型2、JMM的核心概念1&#xff09;主内存与工作内存2&#xff09;内存可见性3&#xff09;JMM的三大特性&#xff1a;原子性、可见性、有序性。 3、JMM中的八种操作4、Happens-before 规则5、样例&#xff1a; 1、Java内存模型 Java内存模型&#xff08;…

电脑文件防泄密软件——天锐绿盾 - 中科数安—— 哪个好

在选择电脑文件防泄密软件时&#xff0c;天锐绿盾和中科数安都是值得考虑的选项。以下是对这两款软件的详细比较&#xff1a; www.drhchina.com PC地址&#xff1a; https://isite.baidu.com/site/wjz012xr/2eae091d-1b97-4276-90bc-6757c5dfedee 功能全面性&#xff1a; 天锐…

QT工作笔记

文章目录 QDialog的accept()和reject()介绍QPushButton提示属性样式表QComboBox QDialog的accept()和reject()介绍 accept() 和reject() 这两个槽函数都会和close() 一样关闭dialogaccept() 关闭后 返回了Dialog::Acceptedreject() 关闭后 返回了Dialog::Rejected这样当我们需…