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

文章目录

    • 完整代码
    • 一、上传资源
    • 二、替换 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 = ''  # 输入你的cookiefile_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 requestsheaders = {'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 MultipartEncoderdef get_file(file_path):"""获取文件的二进制数据"""with open(file_path, mode='rb') as f:binary_data = f.read()return binary_dataheaders = {'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 refile_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 Pathdef 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) / fileget_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 = ''  # 输入你的cookiefile_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.mzph.cn/bicheng/29194.shtml

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

相关文章

力扣每日一题 6/17 枚举+双指针

博客主页&#xff1a;誓则盟约系列专栏&#xff1a;IT竞赛 专栏关注博主&#xff0c;后期持续更新系列文章如果有错误感谢请大家批评指出&#xff0c;及时修改感谢大家点赞&#x1f44d;收藏⭐评论✍ 522.最长特殊序列II【中等】 题目&#xff1a; 给定字符串列表 strs &…

【Ubuntu通用压力测试】Ubuntu16.04 CPU压力测试

使用 stress 对CPU进行压力测试 我也是一个ubuntu初学者&#xff0c;分享是Linux的优良美德。写的不好请大佬不要喷&#xff0c;多谢支持。 sudo apt-get update 日常先更新再安装东西不容易出错 sudo apt-get upgrade -y 继续升级一波 sudo apt-get install -y linux-tools…

Stable Diffusion文生图模型训练入门实战(完整代码)

Stable Diffusion 1.5&#xff08;SD1.5&#xff09;是由Stability AI在2022年8月22日开源的文生图模型&#xff0c;是SD最经典也是社区最活跃的模型之一。 以SD1.5作为预训练模型&#xff0c;在火影忍者数据集上微调一个火影风格的文生图模型&#xff08;非Lora方式&#xff…

Python | Leetcode Python题解之第162题寻找峰值

题目&#xff1a; 题解&#xff1a; class Solution:def findPeakElement(self, nums: List[int]) -> int:n len(nums)# 辅助函数&#xff0c;输入下标 i&#xff0c;返回 nums[i] 的值# 方便处理 nums[-1] 以及 nums[n] 的边界情况def get(i: int) -> int:if i -1 or…

STM32单片机DMA存储器详解

文章目录 1. DMA概述 2. 存储器映像 3. DMA框架图 4. DMA请求 5. 数据宽度与对齐 6. DMA数据转运 7. ADC扫描模式和DMA 8. 代码示例 1. DMA概述 DMA&#xff08;Direct Memory Access&#xff09;可以直接访问STM32内部的存储器&#xff0c;DMA是一种技术&#xff0c;…

【 ARMv8/ARMv9 硬件加速系列 3.5.1 -- SVE 谓词寄存器有多少位?】

文章目录 SVE 谓词寄存器(predicate registers)简介SVE 谓词寄存器的位数SVE 谓词寄存器对向量寄存器的控制SVE 谓词寄存器位数计算SVE 谓词寄存器小结SVE 谓词寄存器(predicate registers)简介 ARMv9的Scalable Vector Extension (SVE) 引入了谓词寄存器(Predicate Register…

打造工业操作系统开源开放体系

我国制造业具有细分行业、领域众多&#xff0c;产品丰富&#xff0c;制造模式多样等特点&#xff0c;围绕以工业操作系统为核心的工业软件赋能体系建设&#xff0c;离不开平台运营商、工业软件开发商、系统服务商、科研机构、工业企业等多方联合参与。聚众同行、聚力创新&#…

【数据库系统概论复习】关系数据库与关系代数笔记

文章目录 基本概念数据库基本概念关系数据结构完整性约束 关系代数关系代数练习课堂练习 语法树 基本概念 数据库基本概念 DB 数据库&#xff0c; 为了存用户的各种数据&#xff0c;我们要建很多关系&#xff08;二维表&#xff09;&#xff0c;所以把相关的关系&#xff08;二…

创建型模式--抽象工厂模式

产品族创建–抽象工厂模式 工厂方法模式通过引入工厂等级结构,解决了简单工厂模式中工厂类职责太重的问题。 但由于工厂方法模式中的每个工厂只生产一类产品,可能会导致系统中存在大量的工厂类,势必会增加系统的开销。此时,可以考虑将一些相关的产品组成一个“产品族”,…

Java基础16(集合 List)

目录 一、什么是集合&#xff1f; 二、集合接口 三、List集合 1. ArrayList容器类 1.1 常用方法 1.1.1 增加 1.1.2 查找 int size() E get(int index) int indexOf(Object c) boolean contains(Object c) boolean isEmpty() List SubList(int fromindex,i…

运行SpringBoot项目失败?代码出现爆红横线,提示“No beans of ‘UserService‘ type found”让我来看看~

今天在做实验运行项目的时候&#xff0c;发现userService&#xff1a; 一直在提示“No beans of UserService type found”&#xff0c;回去翻了Service业务层的代码&#xff0c;Service注解我也加了呀&#xff0c;奇了怪了。 运行项目&#xff0c;出现了这样的提示&#xff1…

判断一组数据哪些是素数,并统计一个数组中元素的出现频率

import java.util.HashMap; import java.util.Map; public class Test_A26 {//判断一个数是不是素数public static boolean isPrime(int num){if(num<1){return false;}for(int i2;i<Math.sqrt(num);i){if(num%i0){return false;}}return true;}//统计数组中出现的频率 p…

python安装目录文件说明----Dlls文件夹

在Python的安装目录下&#xff0c;通常会有一个DLLs文件夹&#xff0c;它是Python标准库的一部分。这个文件夹包含了一些动态链接库&#xff08;Dynamic Link Libraries&#xff0c;DLL&#xff09;&#xff0c;这些库提供了Python解释器和标准库的一些关键功能。以下是对这个文…

模拟自动滚动并展开所有评论列表以及回复内容(如:抖音、b站等平台)

由于各大视频平台的回复内容排序不都是按照时间顺序&#xff0c;而且想看最新的评论回复讨论内容还需逐个点击展开&#xff0c;真的很蛋疼&#xff0c;尤其是热评很多的情况&#xff0c;还需要多次点击展开&#xff0c;太麻烦&#xff01; 于是写了一个自动化展开所有评论回复…

Kaggle比赛:成人人口收入分类

拿到数据首先查看数据信息和描述 import pandas as pd import seaborn as sns import matplotlib.pyplot as plt # 加载数据&#xff08;保留原路径&#xff0c;但在实际应用中建议使用相对路径或环境变量&#xff09; data pd.read_csv(r"C:\Users\11794\Desk…

嵌入式技术学习——c51——串口

一、串口介绍。 串口是一个 通讯接口。成本低&#xff0c;容易使用&#xff0c;通信线路简单&#xff0c;可实现两个设备的相互通信 单片机的串口可以实现单片机于单片机&#xff0c;单片机与电脑&#xff0c;单片机与其他模块相互通信。 51单片机内部自带UART&#xff0c;通…

Flutter图像编辑器应用:创造生动美丽的照片体验

介绍 引言 想象一下&#xff0c;在一个阳光明媚的下午&#xff0c;与家人或朋友漫步在风景如画的街道上。拿出手机&#xff0c;迫不及待地捕捉这一刻的美好&#xff0c;按下快门&#xff0c;留下了一张充满回忆的照片。 然而&#xff0c;回到家后发现照片的亮度有些偏暗&…

【完结】无代码网页爬虫软件——八爪鱼采集器入门基础教程

《八爪鱼采集器入门基础教程》大纲如下&#xff1a; 课程所提软件&#xff0c;八爪鱼采集器下载&#xff1a; 1.软件分享[耶]八爪鱼&#xff0c;爬取了几百条网站上的公开数据&#xff0c;不用学代码真的很方便。[得意]2.发现了一个很棒的软件&#xff0c;?不用学python也可…

周跳的探测及修复

前言&#xff1a; 本章节代码均在Gitee中开源&#xff1a; 导航工程: 导航工程及其有关的所有项目 - Gitee.comhttps://gitee.com/Ehundred/navigation-engineering/tree/master/%E5%8D%AB%E6%98%9F%E5%AF%BC%E8%88%AA%E5%8E%9F%E7%90%86/%E5%91%A8%E8%B7%B3%E6%8E%A2%E6%B5%…

什么是Vue开发技术

概述 Vue.js 是一个用于构建用户界面的渐进式框架&#xff0c;它设计得非常灵活&#xff0c;可以轻松地被集成到任何项目中。 vue是视图的发音&#xff0c;其目的是帮助开发者易于上手&#xff0c;提供强大的功能构建复杂的应用程序 示例 以下是vue基本的语法概述 声明式渲…