当前位置: 首页 > news >正文

实用程序:一键提取博客图片链接并批量下载的工具

前言

经常转载博客的朋友可能会遇到一个头疼的问题:很多博客平台不支持直接引用外站图片,导致转载后的文章图片无法正常显示。如果手动一张张找图片链接、复制、下载,不仅效率低,还容易遗漏。

为了解决这个问题,我写了一个「图片链接提取与下载工具」,它能自动从文本中提取Markdown格式的图片链接(即![描述](链接)形式),并批量下载到本地。只需粘贴文本、点击提取、再点下载,所有图片就能自动保存,彻底告别手动操作的繁琐。

代码仓库已经上传到github 可以通过链接直接下载:
https://github.com/ChenAI-TGF/Extract_Fig_From_Markdown

简要代码原理介绍

这个工具的核心功能分为两部分:图片链接提取批量下载,我们重点看这两部分的逻辑实现。

1. 图片链接提取逻辑

Markdown中图片的标准格式是![图片描述](图片链接),比如![示例图](https://example.com/image.jpg)。我们需要从中提取出括号里的图片链接,这里用到了正则表达式:

# 正则表达式匹配![描述](链接)格式
pattern = r'!\[.*?\]\((.*?)\)'
self.image_links = re.findall(pattern, text)
  • 正则表达式r'!\[.*?\]\((.*?)\)'的作用:
    • !\[.*?\]匹配![图片描述]部分(.*?表示非贪婪匹配,避免匹配到多个图片时出错);
    • \((.*?)\)匹配(图片链接)部分,其中(.*?)会捕获括号里的链接内容;
    • re.findall会提取所有符合格式的链接,存到image_links列表中。

2. 批量下载逻辑

提取到链接后,需要将图片批量下载到本地,核心步骤如下:

  1. 创建存储文件夹:自动在程序所在目录创建image文件夹,用于存放下载的图片:

    image_dir = os.path.join(os.path.dirname(os.path.abspath(__file__)), "image")
    if not os.path.exists(image_dir):os.makedirs(image_dir)
    
  2. 遍历链接并下载:循环处理每个提取到的链接,用requests库发送请求获取图片数据:

    for i, link in enumerate(self.image_links, 1):# 发送请求获取图片response = requests.get(link, timeout=10, stream=True)response.raise_for_status()  # 检查请求是否成功(比如404、500错误)
    
  3. 处理文件格式:自动识别链接中的文件扩展名(如jpg、png),如果格式不常见则默认保存为jpg:

    if '.' in link:ext = link.split('.')[-1].lower()# 限制常见图片扩展名if ext not in ['jpg', 'jpeg', 'png', 'gif', 'bmp', 'webp']:ext = 'jpg'
    else:ext = 'jpg'
    
  4. 保存图片:分块写入图片数据(适合大文件),避免内存占用过高:

    filename = f"{i}.{ext}"  # 用序号命名,如1.jpg、2.png
    file_path = os.path.join(image_dir, filename)
    with open(file_path, 'wb') as f:for chunk in response.iter_content(chunk_size=1024):if chunk:  # 过滤空块f.write(chunk)
    
  5. 异常处理与进度反馈:下载过程中会捕获错误(如链接失效、网络问题)并提示,同时通过进度条实时显示下载进度。

完整代码

import tkinter as tk
from tkinter import scrolledtext, ttk, messagebox
import re
import requests
import os
from threading import Thread
import timeclass ImageLinkExtractor:def __init__(self, root):self.root = rootself.root.title("图片链接提取与下载工具")self.root.geometry("800x600")self.root.resizable(True, True)# 设置中文字体支持self.font = ('SimHei', 10)# 创建UI组件self.create_widgets()# 存储提取到的链接self.image_links = []def create_widgets(self):# 创建主框架main_frame = ttk.Frame(self.root, padding="10")main_frame.pack(fill=tk.BOTH, expand=True)# 文本输入区域ttk.Label(main_frame, text="请输入包含图片链接的文本:", font=self.font).pack(anchor=tk.W)self.text_input = scrolledtext.ScrolledText(main_frame, wrap=tk.WORD, font=self.font)self.text_input.pack(fill=tk.BOTH, expand=True, pady=(5, 10))# 按钮区域button_frame = ttk.Frame(main_frame)button_frame.pack(fill=tk.X, pady=(0, 10))self.extract_btn = ttk.Button(button_frame, text="提取链接", command=self.extract_links)self.extract_btn.pack(side=tk.LEFT, padx=(0, 10))self.download_btn = ttk.Button(button_frame, text="下载图片", command=self.start_download, state=tk.DISABLED)self.download_btn.pack(side=tk.LEFT)# 进度条self.progress_var = tk.DoubleVar()self.progress_bar = ttk.Progressbar(main_frame, variable=self.progress_var, length=100)self.progress_bar.pack(fill=tk.X, pady=(0, 10))# 结果显示区域ttk.Label(main_frame, text="提取结果与状态:", font=self.font).pack(anchor=tk.W)self.result_text = scrolledtext.ScrolledText(main_frame, wrap=tk.WORD, font=self.font, height=10)self.result_text.pack(fill=tk.BOTH, expand=True)self.result_text.config(state=tk.DISABLED)def log(self, message):"""在结果区域显示消息"""self.result_text.config(state=tk.NORMAL)self.result_text.insert(tk.END, message + "\n")self.result_text.see(tk.END)self.result_text.config(state=tk.DISABLED)def extract_links(self):"""从文本中提取图片链接"""text = self.text_input.get("1.0", tk.END)# 正则表达式匹配![描述](链接)格式pattern = r'!\[.*?\]\((.*?)\)'self.image_links = re.findall(pattern, text)if self.image_links:self.log(f"成功提取到 {len(self.image_links)} 个图片链接:")for i, link in enumerate(self.image_links, 1):self.log(f"{i}. {link}")self.download_btn.config(state=tk.NORMAL)else:self.log("未找到任何图片链接")self.download_btn.config(state=tk.DISABLED)def start_download(self):"""开始下载图片(在新线程中执行以避免UI冻结)"""if not self.image_links:messagebox.showwarning("警告", "没有可下载的图片链接")return# 禁用按钮防止重复操作self.extract_btn.config(state=tk.DISABLED)self.download_btn.config(state=tk.DISABLED)# 启动下载线程Thread(target=self.download_images, daemon=True).start()def download_images(self):"""下载图片并保存到image文件夹"""# 创建image文件夹image_dir = os.path.join(os.path.dirname(os.path.abspath(__file__)), "image")if not os.path.exists(image_dir):os.makedirs(image_dir)self.log(f"已创建image文件夹: {image_dir}")total = len(self.image_links)success_count = 0for i, link in enumerate(self.image_links, 1):try:self.log(f"正在下载第 {i}/{total} 张图片...")# 发送请求response = requests.get(link, timeout=10, stream=True)response.raise_for_status()  # 检查请求是否成功# 获取文件扩展名if '.' in link:ext = link.split('.')[-1].lower()# 限制常见图片扩展名if ext not in ['jpg', 'jpeg', 'png', 'gif', 'bmp', 'webp']:ext = 'jpg'else:ext = 'jpg'# 保存文件filename = f"{i}.{ext}"file_path = os.path.join(image_dir, filename)with open(file_path, 'wb') as f:for chunk in response.iter_content(chunk_size=1024):if chunk:f.write(chunk)success_count += 1self.log(f"成功保存: {filename}")except Exception as e:self.log(f"下载失败 (第 {i} 个链接): {str(e)}")# 更新进度条progress = (i / total) * 100self.progress_var.set(progress)self.root.update_idletasks()# 稍微延迟一下,避免请求过于频繁time.sleep(0.1)# 下载完成self.progress_var.set(100)self.log(f"\n下载完成!成功下载 {success_count}/{total} 张图片")self.log(f"图片保存路径: {image_dir}")# 恢复按钮状态self.extract_btn.config(state=tk.NORMAL)self.download_btn.config(state=tk.NORMAL)# 显示完成消息messagebox.showinfo("完成", f"下载完成!成功下载 {success_count}/{total} 张图片\n保存路径: {image_dir}")if __name__ == "__main__":root = tk.Tk()app = ImageLinkExtractor(root)root.mainloop()

效果演示

  1. 打开工具:运行代码后,会显示一个图形界面,包含文本输入区、提取/下载按钮、进度条和结果显示区。
    在这里插入图片描述

  2. 输入文本:将包含Markdown图片格式的文本(比如从博客复制的内容)粘贴到上方的文本输入区,例如:

    这是一篇测试文章,包含3张图片:
    ![外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传](https://img-home.csdnimg.cn/images/20230724024159.png?origin_url=https%3A%2F%2Fexample.com%2Fimg1.jpg&pos_id=img-1hg7yUwV-1763282765960)
    ![外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传](https://img-home.csdnimg.cn/images/20230724024159.png?origin_url=https%3A%2F%2Fexample.com%2Fimg2.png&pos_id=img-gW28j81E-1763282765961)
    ![外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传](https://img-home.csdnimg.cn/images/20230724024159.png?origin_url=https%3A%2F%2Fexample.com%2Fimg3.webp&pos_id=img-d5i77pbw-1763282765961)
    
  3. 提取链接:点击「提取链接」按钮,工具会自动识别并显示所有图片链接,结果区会显示提取到的链接数量和具体地址,此时「下载图片」按钮变为可点击状态。
    在这里插入图片描述

  4. 批量下载:点击「下载图片」按钮,工具会在程序所在目录创建image文件夹,并开始下载图片。进度条会实时显示下载进度,结果区会提示每张图片的下载状态(成功/失败原因)。
    5.

  5. 查看结果:下载完成后,会弹出提示框显示成功数量和保存路径,打开image文件夹就能看到所有下载的图片(按1.jpg、2.png等序号命名)。

有了这个工具,转载博客时处理图片的效率能提升不少,再也不用手动一个个下载了。如果需要处理其他格式的图片链接,也可以通过修改正则表达式来适配,非常灵活~

http://www.dtcms.com/a/618161.html

相关文章:

  • 破解入门学习笔记题四十七
  • 登陆国外网站速度慢网站重构案例
  • 百日挑战——单词篇(第二十三天)
  • 基于Flask + ECharts的个人财务仪表盘 -(上个记账本的优化MAX)
  • Galois 理论 | 发展历程 / 基本定理的证明
  • 给定一个数组,如何用最小的比较次数获得最大最小值
  • 个人网站免费源码大全南宁seo管理
  • Linux服务器崩溃急救指南:快速诊断与恢复
  • 后端服务发现配置
  • wordpress建的手机网站合肥信息网
  • 我爱学算法之—— 字符串
  • 关于Function JS加密加密(仅于问题分析)
  • mysql基础——视图
  • win系统做网站wordpress侧边文本轮播图片
  • 免费微商城平台官网一直在做竞价的网站是不是不需要做seo
  • 输出纹波实测:ASP3605在不同输入与负载条件下的稳定性表现
  • RAG向量索引-HNSW Hierarchical Navigable Small World 介绍
  • 沈阳做网站的企业重庆房产网站建设
  • 让老版 IntelliJ IDEA 2020.1.4 支持 JDK 17 启动 springboot3 项目
  • 网站开发逻辑商丘网站建设求职简历
  • [Linux网络——Lesson1.初识计算机网络]
  • 电子电气架构全解析
  • 5G技术:推动数字经济的下一个革命性浪潮
  • 5G与AI赋能智能制造:未来生产的双重驱动力
  • 从工业互联网到智慧城市:5G与物联网的跨界融合
  • 5G NR PBCH与MIB技术介绍
  • 怎么查询网站的点击量招商网站建设全包
  • TCN‑Transformer‑GRU(单输入‑单输出)在 MATLAB 中的实现思路与完整示例代码
  • 重庆市建设工程信息网站诚信分东莞海天网站建设
  • 【Linux】文件操作篇(二):实战理解硬链接与软链接