cnblog批量上传图片脚本小记

news/2026/1/16 23:52:45/文章来源:https://www.cnblogs.com/shenleblog/p/19494342

原因

在博客园后台没发现能一次性上传多张图片的选项,功能
在vsc的插件里面也得每次先复制到粘贴板,再快捷键复制一张
之前某些情况上传需要上传多张图片,都是一张一张传的,
希望下次能有个简便的方法,所以用 ai 写了个py脚本
(非专业,ai生成较为臃肿)

依赖

脚本依赖

pip install requests  #用来发送HTTP POST请求

链接博客园需要metaweblog访问令牌(博客园设置最下方)
img


测试脚本

测试能否成功连接博客园,顺便查看下自己的博客id

import xmlrpc.client# 请将以下变量替换为你的真实凭证
API_URL = ""   # 你的博客园metaweblog API地址,通常是 https://rpc.cnblogs.com/metaweblog/你的博客园用户名
USERNAME = ""  # 你的博客园登录用户名
PASSWORD = "" # 你的令牌def get_blog_id():"""通过API获取博客ID"""try:server = xmlrpc.client.ServerProxy(API_URL)# 调用 blogger.getUsersBlogs 方法blogs = server.blogger.getUsersBlogs('', USERNAME, PASSWORD)if blogs:print("✅ 连接成功!你的博客信息如下:\n")# 通常用户只有一个博客,取第一个即可blog = blogs[0]print(f"   博客ID (blogid): {blog['blogid']}")print(f"   博客名称: {blog['blogName']}")print(f"   博客地址: {blog['url']}")print(f"\n🎯 请将以下 blogid 用于你的上传脚本:")print(f"   BLOG_ID = \"{blog['blogid']}\"")return blog['blogid']else:print("未找到博客信息。")return Noneexcept xmlrpc.client.Fault as e:# 处理API级别的错误(如密码错误)print(f"❌ API调用失败 [错误码 {e.faultCode}]: {e.faultString}")if e.faultCode == 801:print("提示:这通常意味着用户名或密码/令牌不正确。请检查你的凭证。")return Noneexcept Exception as e:# 处理网络连接等其他错误print(f"❌ 发生错误: {e}")return Noneif __name__ == "__main__":get_blog_id()

输出示例

(base) PS E:\project_wu\ps1_documents> python .\getblog.py博客ID (blogid): XXXXXX博客名称: ( ̄ .  ̄)博客地址: https://www.cnblogs.com/shenleblog/🎯 请将以下 blogid 用于你的上传脚本:BLOG_ID = "XXXXXX"

上传复数图片脚本

  1. 将所有图片放置在同一文件夹,执行脚本
  2. 可修改“默认路径”:DEFAULT_FOLDER
  3. 也可在脚本后输入参数,指定文件夹路径
#!/usr/bin/env python3
"""
博客园图片批量上传脚本
基于手动构建XML-RPC请求。
用法:python blog_imgload_final.py [图片文件夹路径]
"""import base64
import xml.etree.ElementTree as ET
import requests
import sys
import os
import argparse
from pathlib import Path# ============== 你的配置 ==============
API_URL = ""   # 你的博客园metaweblog API地址,通常是 https://rpc.cnblogs.com/metaweblog/你的博客园用户名
USERNAME = ""  # 你的博客园登录用户名
PASSWORD = "" # 你的令牌
BLOG_ID = ""  #理论上可以为0
# =====================================SUPPORTED_EXTENSIONS = {'.jpg', '.jpeg', '.png', '.gif', '.bmp', '.webp'}def build_xml_request(image_path):"""手动构建XML-RPC请求体(已验证的核心函数)"""with open(image_path, 'rb') as f:image_bytes = f.read()base64_data = base64.b64encode(image_bytes).decode('ascii')method_call = ET.Element('methodCall')method_name = ET.SubElement(method_call, 'methodName')method_name.text = 'metaWeblog.newMediaObject'params = ET.SubElement(method_call, 'params')# 四个参数:blogid, username, password, file structfor text in [BLOG_ID, USERNAME, PASSWORD]:param = ET.SubElement(params, 'param')value = ET.SubElement(param, 'value')string_elem = ET.SubElement(value, 'string')string_elem.text = text# 构建 file structparam4 = ET.SubElement(params, 'param')value4 = ET.SubElement(param4, 'value')struct = ET.SubElement(value4, 'struct')# bits (base64)member1 = ET.SubElement(struct, 'member')name1 = ET.SubElement(member1, 'name'); name1.text = 'bits'value_m1 = ET.SubElement(member1, 'value')base64_elem = ET.SubElement(value_m1, 'base64'); base64_elem.text = base64_data# name (string)member2 = ET.SubElement(struct, 'member')name2 = ET.SubElement(member2, 'name'); name2.text = 'name'value_m2 = ET.SubElement(member2, 'value')string_m2 = ET.SubElement(value_m2, 'string'); string_m2.text = os.path.basename(image_path)# type (string)member3 = ET.SubElement(struct, 'member')name3 = ET.SubElement(member3, 'name'); name3.text = 'type'value_m3 = ET.SubElement(member3, 'value')string_m3 = ET.SubElement(value_m3, 'string')ext = os.path.splitext(image_path)[1].lower()mime_type = f'image/{ext[1:]}' if ext in ['.jpg', '.jpeg', '.png', '.gif', '.bmp'] else 'application/octet-stream'string_m3.text = mime_typexml_str = ET.tostring(method_call, encoding='utf-8', method='xml').decode('utf-8')return f"<?xml version='1.0' encoding='UTF-8'?>\n{xml_str}"def upload_single_image(image_path):"""上传单张图片并返回URL,集成到批量处理中"""print(f"  正在处理: {os.path.basename(image_path)} (大小: {os.path.getsize(image_path)} 字节)")xml_body = build_xml_request(image_path)headers = {'Content-Type': 'text/xml; charset=utf-8'}try:response = requests.post(API_URL, data=xml_body.encode('utf-8'), headers=headers, timeout=30)response.raise_for_status()# 解析XML响应,提取URLroot = ET.fromstring(response.text)fault = root.find('.//fault')if fault is not None:# 提取错误信息fault_string = fault.find('.//string')if fault_string is not None and fault_string.text:print(f"  ❌ 上传失败: {fault_string.text}")else:print(f"  ❌ 上传失败: API返回错误结构")return None# 查找返回的URL (响应中的第一个<string>标签内容)url_elem = root.find('.//string')if url_elem is not None and url_elem.text:image_url = url_elem.textprint(f"  ✅ 上传成功!")return image_urlelse:print(f"  ❌ 上传失败: 响应中未找到URL")return Noneexcept requests.exceptions.RequestException as e:print(f"  ❌ 网络请求失败: {e}")return Noneexcept Exception as e:print(f"  ❌ 意外错误: {type(e).__name__}: {e}")return Nonedef main():# 设置默认路径DEFAULT_FOLDER = r"D:\cp_default\Pictures\temp"parser = argparse.ArgumentParser(description='批量上传图片到博客园',formatter_class=argparse.RawDescriptionHelpFormatter,epilog=f"""
使用示例:%(prog)s                    # 使用默认路径: {DEFAULT_FOLDER}%(prog)s "C:\\MyImages"     # 使用自定义路径""")parser.add_argument('folder', type=str, nargs='?',  # 使参数变为可选default=DEFAULT_FOLDER,help=f'包含图片的文件夹路径 (默认: {DEFAULT_FOLDER})')args = parser.parse_args()folder_path = Path(args.folder)if not folder_path.is_dir():print(f"错误: '{args.folder}' 不是一个有效的文件夹路径")sys.exit(1)print(f"博客园图片批量上传 - 使用路径: {folder_path}")print("=" * 60)# 使用集合(Set)自动去重,再转换为列表image_files_set = set()for file_path in folder_path.rglob('*'):if file_path.is_file():if file_path.suffix.lower() in SUPPORTED_EXTENSIONS:# 使用文件的绝对路径作为集合的键,确保唯一性image_files_set.add(file_path.resolve())# 将集合转换回列表以便后续遍历image_files = list(image_files_set)if not image_files:print(f"在 '{args.folder}' 中未找到支持的图片文件")print(f"支持格式: {', '.join(SUPPORTED_EXTENSIONS)}")returnprint(f"找到 {len(image_files)} 张待上传图片\n")# 上传所有图片并收集链接markdown_links = []success_count = 0for image_file in image_files:url = upload_single_image(str(image_file))if url:markdown_links.append(f"![img]({url})")success_count += 1print()  # 空行分隔# 输出最终结果print("=" * 60)if success_count > 0:print(f"批量上传完成!成功 {success_count}/{len(image_files)} 张")print("Markdown链接如下:\n")for link in markdown_links:print(link)else:print("所有图片上传均失败")print("\n提示:你可以直接复制以上链接到你的博客文章编辑器中。")if __name__ == "__main__":main()

输出示例

(base) PS E:\project_wu\ps1_documents> python blog_imgload_final.py                              
博客园图片批量上传 - 使用路径: D:\cp_default\Pictures\temp
============================================================
找到 5 张待上传图片正在处理: 【哲风壁纸】云-动漫云-动漫天空.png (大小: 9124711 字节)✅ 上传成功!正在处理: 【哲风壁纸】云城-云漩涡-光影.png (大小: 1436233 字节)✅ 上传成功!正在处理: test1.png (大小: 547830 字节)✅ 上传成功!正在处理: 【哲风壁纸】云-亚洲建筑.png (大小: 542527 字节)✅ 上传成功!正在处理: 【哲风壁纸】游戏摄影-黑神话.png (大小: 1597735 字节)✅ 上传成功!============================================================
批量上传完成!成功 5/5 张
Markdown链接如下:![img](https://img2024.cnblogs.com/blog/3084836/202601/3084836-20260116232410555-974674461.png)
![img](https://img2024.cnblogs.com/blog/3084836/202601/3084836-20260116232413893-390923406.png)
![img](https://img2024.cnblogs.com/blog/3084836/202601/3084836-20260116232415380-503402962.png)     
![img](https://img2024.cnblogs.com/blog/3084836/202601/3084836-20260116232416785-485332796.png)     
![img](https://img2024.cnblogs.com/blog/3084836/202601/3084836-20260116232418405-1163868482.png)   

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

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

相关文章

Java毕设项目:基于 Web Service 技术的警务数据交互平台设计与实现(源码+文档,讲解、调试运行,定制等)

博主介绍&#xff1a;✌️码农一枚 &#xff0c;专注于大学生项目实战开发、讲解和毕业&#x1f6a2;文撰写修改等。全栈领域优质创作者&#xff0c;博客之星、掘金/华为云/阿里云/InfoQ等平台优质作者、专注于Java、小程序技术领域和毕业项目实战 ✌️技术范围&#xff1a;&am…

计算机Java毕设实战-基于SpringBoot的校园设备维护报修系统基于springboot的高校教室设备故障报修信息管理系统【完整源码+LW+部署说明+演示视频,全bao一条龙等】

博主介绍&#xff1a;✌️码农一枚 &#xff0c;专注于大学生项目实战开发、讲解和毕业&#x1f6a2;文撰写修改等。全栈领域优质创作者&#xff0c;博客之星、掘金/华为云/阿里云/InfoQ等平台优质作者、专注于Java、小程序技术领域和毕业项目实战 ✌️技术范围&#xff1a;&am…

计算机Java毕设实战-基于SpringBoot的大学生体测数据管理系统【完整源码+LW+部署说明+演示视频,全bao一条龙等】

博主介绍&#xff1a;✌️码农一枚 &#xff0c;专注于大学生项目实战开发、讲解和毕业&#x1f6a2;文撰写修改等。全栈领域优质创作者&#xff0c;博客之星、掘金/华为云/阿里云/InfoQ等平台优质作者、专注于Java、小程序技术领域和毕业项目实战 ✌️技术范围&#xff1a;&am…

计算机Java毕设实战-基于 Web Service 技术的警务数据交互平台设计与实现【完整源码+LW+部署说明+演示视频,全bao一条龙等】

博主介绍&#xff1a;✌️码农一枚 &#xff0c;专注于大学生项目实战开发、讲解和毕业&#x1f6a2;文撰写修改等。全栈领域优质创作者&#xff0c;博客之星、掘金/华为云/阿里云/InfoQ等平台优质作者、专注于Java、小程序技术领域和毕业项目实战 ✌️技术范围&#xff1a;&am…

Linux 内网环境构建与配置深度解析

在企业级 IT 基础设施的搭建过程中&#xff0c;内网环境的稳定性直接决定了服务集群的运行质量。Linux 系统作为服务器领域的主流操作系统&#xff0c;其网络配置的灵活性极高&#xff0c;但也对管理者的严谨性提出了挑战。构建一个高效的内网&#xff0c;需要从物理链路的识别…

Git 从入门到封神:一站式精通 Git 所有核心用法(零基础 → 进阶 → 大神级实战,万字干货)

前言 作为程序员&#xff0c;Git 是我们职业生涯中最基础、最重要、使用率最高的必备技能&#xff0c;没有之一。无论是前端、后端、移动端、大数据还是运维开发&#xff0c;只要涉及到代码开发、项目协作、版本管理&#xff0c;Git 都是绕不开的核心工具。 很多人对 Git 的认知…

手撸工业级Socket客户端是什么体验

Socket通信源码&#xff0c;客户端部分&#xff0c;这是从一个商业级的物联网项目分离出来的核心代码&#xff0c;c#语言多线程&#xff0c;有400行&#xff0c;让你绕过最难写的Socket管理&#xff0c;功能带有断线重连&#xff0c;仅一个静态类文件&#xff0c;c#下直接使用&…

04谓词逻辑基本概念

04谓词逻辑基本概念论域:个体域

新能源汽车整车控制器VCU学习模型,适用于初学者。 1、模型包含高压上下电,行驶模式管理,能量...

新能源汽车整车控制器VCU学习模型&#xff0c;适用于初学者。 1、模型包含高压上下电&#xff0c;行驶模式管理&#xff0c;能量回馈&#xff0c;充电模式管理&#xff0c;附件管理&#xff0c;远程控制&#xff0c;诊断辅助功能。 2、软件说明书&#xff08;控制策略说明书&am…

新能源汽车整车控制器VCU学习模型,适用于初学者。 1、模型包含高压上下电,行驶模式管理,能量...

新能源汽车整车控制器VCU学习模型&#xff0c;适用于初学者。 1、模型包含高压上下电&#xff0c;行驶模式管理&#xff0c;能量回馈&#xff0c;充电模式管理&#xff0c;附件管理&#xff0c;远程控制&#xff0c;诊断辅助功能。 2、软件说明书&#xff08;控制策略说明书&am…

计算机Java毕设实战-基于SpringBoot+vue的高校学生实习综合服务平台设计与实现【完整源码+LW+部署说明+演示视频,全bao一条龙等】

博主介绍&#xff1a;✌️码农一枚 &#xff0c;专注于大学生项目实战开发、讲解和毕业&#x1f6a2;文撰写修改等。全栈领域优质创作者&#xff0c;博客之星、掘金/华为云/阿里云/InfoQ等平台优质作者、专注于Java、小程序技术领域和毕业项目实战 ✌️技术范围&#xff1a;&am…

威纶通触摸屏与三菱变频器modbus通讯 威纶通与三菱变频器直接相连,进行modbus通讯

威纶通触摸屏与三菱变频器modbus通讯 威纶通与三菱变频器直接相连&#xff0c;进行modbus通讯&#xff0c;程序可以帮你学会触摸屏直连的modbus通讯&#xff0c;触摸屏有三种mt6070ih,tk6070ih,k6070ip最近在搞工控项目时遇到个需求&#xff1a;用威纶通触摸屏直接控制三菱变频…

基于Qt5+osg3.4+opencascade7.0开发的三维CAD,目前软件支持主流的3D...

基于Qt5osg3.4opencascade7.0开发的三维CAD&#xff0c;目前软件支持主流的3D格式文件&#xff08;比如igs,stop,stl,obj,3ds等&#xff09;&#xff0c;文件可以另存为obj,stl,osg等&#xff0c;软件整体采用Qt MDI多文档结构&#xff0c;支持模型放大缩小&#xff0c;拖动&a…

Java毕设项目:基于SpringBoot+vue的高校学生实习综合服务平台设计与实现(源码+文档,讲解、调试运行,定制等)

博主介绍&#xff1a;✌️码农一枚 &#xff0c;专注于大学生项目实战开发、讲解和毕业&#x1f6a2;文撰写修改等。全栈领域优质创作者&#xff0c;博客之星、掘金/华为云/阿里云/InfoQ等平台优质作者、专注于Java、小程序技术领域和毕业项目实战 ✌️技术范围&#xff1a;&am…

AI应用架构师揭秘AI驱动的元宇宙金融的合规性问题

AI应用架构师揭秘&#xff1a;AI驱动的元宇宙金融的合规性困局与破局之道 一、引言&#xff1a;当元宇宙金融撞上合规“墙” 1.1 一个真实的“元宇宙金融合规事故” 2023年11月&#xff0c;某海外元宇宙平台推出“AI数字人贷款”服务&#xff1a;用户通过虚拟形象提交身份信息&…

直接上干货,这个旋转编码器记米模块我在纺织机械和包装设备上用过不下十次。核心就俩字——抗造!先看PLC程序,再聊触摸屏怎么配

三菱plcFX3U结合旋转编码器记米数万能模块程序&#xff0c;本人已实际项目中应用多次&#xff0c;现单独编写一段通用模块出来&#xff0c;其中难点在于如何处理计数器溢出&#xff0c;及相关数据运算&#xff01;算是非常实用的程序块&#xff01; 内容包括&#xff1a; 1.三菱…

【课程设计/毕业设计】基于SpringBoot+vue的高校学生实习综合服务平台设计与实现【附源码、数据库、万字文档】

博主介绍&#xff1a;✌️码农一枚 &#xff0c;专注于大学生项目实战开发、讲解和毕业&#x1f6a2;文撰写修改等。全栈领域优质创作者&#xff0c;博客之星、掘金/华为云/阿里云/InfoQ等平台优质作者、专注于Java、小程序技术领域和毕业项目实战 ✌️技术范围&#xff1a;&am…

Java毕设项目推荐-基于vue的高校学生实习综合服务平台设计与实现基于SpringBoot+vue的高校学生实习综合服务平台设计与实现【附源码+文档,调试定制服务】

博主介绍&#xff1a;✌️码农一枚 &#xff0c;专注于大学生项目实战开发、讲解和毕业&#x1f6a2;文撰写修改等。全栈领域优质创作者&#xff0c;博客之星、掘金/华为云/阿里云/InfoQ等平台优质作者、专注于Java、小程序技术领域和毕业项目实战 ✌️技术范围&#xff1a;&am…

Java计算机毕设之基于Spring Boot的高校应届生实习综合管理系统设计与实现基于SpringBoot+vue的高校学生实习综合服务平台设计与实现(完整前后端代码+说明文档+LW,调试定制等)

博主介绍&#xff1a;✌️码农一枚 &#xff0c;专注于大学生项目实战开发、讲解和毕业&#x1f6a2;文撰写修改等。全栈领域优质创作者&#xff0c;博客之星、掘金/华为云/阿里云/InfoQ等平台优质作者、专注于Java、小程序技术领域和毕业项目实战 ✌️技术范围&#xff1a;&am…

搭建 FreeIPA Server 实现统一认证

FreeIPA(Free Identity Policy and Audit)是 Linux/Unix 世界的 "Active Directory",一个开源的、一体化的身份管理与集中式策略控制解决方案。它旨在简化并统一在混合环境中管理 Linux 系统和用户的复杂…