【求助】有没有办法自动将剪切板中的图片链接转换为下载好的图片?

RTRT,
在整理网摘的时候,复制网页上带图片的段落文字,实际剪切板中会生成一个html类型的剪切板,比如这个:

<img src="https://cdn.beekka.com/blogimg/asset/202409/bg2024092303.webp" alt="" 
 title="" style="margin: 0px; padding: 0px; list-style-type: none; 
 text-align: left; text-decoration: none; font-weight: normal; font-style: 
 normal; border: 0.3em solid rgb(224, 223, 204); color: rgb(17, 17, 17); 
 border-radius: 1em;">

我写了一个python程序,将图片转换为base64嵌入html中:

import win32clipboard
import win32con
from PIL import Image
import io
import re
import base64
import requests
from io import BytesIO

class ClipboardManager:
    def __enter__(self):
        win32clipboard.OpenClipboard()
        return self
    
    def __exit__(self, exc_type, exc_val, exc_tb):
        win32clipboard.CloseClipboard()


def decode_text(data):
    """使用 chardet 自动检测编码并解码文本"""
    import chardet
    try:
        detected = chardet.detect(data)
        encoding = detected['encoding']
        print(f"Detected encoding: {encoding}")  # 输出检测到的编码
        return data.decode(encoding)
    except Exception as e:
        print(f"Failed to decode text: {e}")
        return data.decode('utf-8', errors='replace')


def extract_image_urls_from_html(html_data):
    """从 HTML 数据中提取图片链接"""
    image_urls = re.findall(r'<img[^>]+src="([^">]+)"', html_data)
    return image_urls


def download_image_as_base64(image_url):
    """下载图片并将其转换为 base64 编码,并根据图片格式生成正确的 MIME 类型"""
    try:
        response = requests.get(image_url)
        if response.status_code == 200:
            image_data = BytesIO(response.content)
            
            # 使用 PIL 来识别图片的格式
            img = Image.open(image_data)
            image_format = img.format.lower()  # 获取图像格式并转换为小写
            
            # 重置指针以重新读取图像数据
            image_data.seek(0)
            
            # 将图片转换为 Base64
            base64_image = base64.b64encode(image_data.read()).decode('utf-8')
            
            # 生成带有正确 MIME 类型的 Base64 数据
            return f"data:image/{image_format};base64,{base64_image}"
        else:
            print(f"Failed to download image: {image_url}")
            return None
    except Exception as e:
        print(f"Error downloading image: {image_url}, error: {e}")
        return None

def download_image_from_html(html_data):
    """从 HTML 数据中提取图片链接,并将其替换为 base64 编码的图片"""
    # 提取所有的图片链接
    image_urls = re.findall(r'<img[^>]+src="([^">]+)"', html_data)
    
    # 遍历找到的图片链接
    for image_url in image_urls:
        # 下载图片并转换为 Base64
        base64_image = download_image_as_base64(image_url)
        
        # 如果下载成功,则替换 HTML 中的图片链接为 Base64 数据
        if base64_image:
            # 将原来的图片 URL 替换为 base64 编码的图片数据
            html_data = html_data.replace(image_url, base64_image)
    
    return html_data


def get_clipboard_format_name(fmt):
    """获取剪切板自定义格式的名称"""
    try:
        name = win32clipboard.GetClipboardFormatName(fmt)
        return name
    except:
        return None


def list_clipboard_formats():
    """列出当前剪切板中的所有格式"""
    formats = []
    fmt = win32clipboard.EnumClipboardFormats(0)
    while fmt:
        formats.append(fmt)
        fmt = win32clipboard.EnumClipboardFormats(fmt)
    return formats


def read_clipboard():
    clipboard_content = {}
    
    with ClipboardManager():
        # 处理 CF_TEXT 格式
        if win32clipboard.IsClipboardFormatAvailable(win32con.CF_TEXT):
            text = win32clipboard.GetClipboardData(win32con.CF_TEXT)
            clipboard_content['CF_TEXT'] = decode_text(text)
        
        # 处理 CF_UNICODETEXT 格式
        if win32clipboard.IsClipboardFormatAvailable(win32con.CF_UNICODETEXT):
            unicode_text = win32clipboard.GetClipboardData(win32con.CF_UNICODETEXT)
            clipboard_content['CF_UNICODETEXT'] = unicode_text
        
        # 处理 CF_BITMAP 格式
        if win32clipboard.IsClipboardFormatAvailable(win32con.CF_BITMAP):
            bitmap_handle = win32clipboard.GetClipboardData(win32con.CF_BITMAP)
            clipboard_content['CF_BITMAP'] = f"Bitmap handle: {bitmap_handle}"
        
        # 注册并获取 HTML 格式的编号
        cf_html = win32clipboard.RegisterClipboardFormat("HTML Format")
        
        # 检查并读取 HTML 内容
        if win32clipboard.IsClipboardFormatAvailable(cf_html):
            html = win32clipboard.GetClipboardData(cf_html)
            html_text = html.decode('utf-8')
            
            pprint.pprint(html_text)
            
            clipboard_content['HTML'] = html_text
            
            # 下载并替换 HTML 中的图片链接为 Base64
            modified_html = download_image_from_html(html_text)
            clipboard_content['HTML'] = modified_html
            
            win32clipboard.SetClipboardData(cf_html, modified_html.encode('utf-8'))
        
        # 处理 CF_DIB 图像格式
        if win32clipboard.IsClipboardFormatAvailable(win32con.CF_DIB):
            image_data = win32clipboard.GetClipboardData(win32con.CF_DIB)
            
            # 将 DIB 数据转换为 PIL 图像
            image = Image.open(io.BytesIO(image_data))
            clipboard_content['IMAGE'] = image
        
        # 处理 CF_HDROP 文件路径
        if win32clipboard.IsClipboardFormatAvailable(win32con.CF_HDROP):
            file_paths = win32clipboard.GetClipboardData(win32con.CF_HDROP)
            clipboard_content['FILES'] = list(file_paths)
        
        # 枚举并读取所有其他剪切板格式
        formats = list_clipboard_formats()
        for fmt in formats:
            # 跳过已处理的常见格式
            if fmt in (
            win32con.CF_TEXT, win32con.CF_UNICODETEXT, win32con.CF_BITMAP, cf_html, win32con.CF_DIB, win32con.CF_HDROP):
                continue
            
            # 尝试获取自定义格式名称
            format_name = get_clipboard_format_name(fmt) or f"Custom Format {fmt}"
            
            # 获取格式内容
            try:
                data = win32clipboard.GetClipboardData(fmt)
                clipboard_content[format_name] = str(data)[:100]  # 截取前100字符避免太长
            except Exception as e:
                clipboard_content[format_name] = f"Error reading format {fmt}: {e}"
    
    return clipboard_content


# 调用函数并打印剪切板内容
import pprint

clipboard_data = read_clipboard()
pprint.pprint(clipboard_data)
print(clipboard_data['HTML'])

但是实际上粘贴进word中是白色的方块,并不是图片。
尝试复制word中的图片,是这个样子:

<v:imagedata          src="file:///C:/Users/ljq29/AppData/Local/Temp/msohtmlclip1/01/clip_image001.png"\r\n
          o:title="图形用户界面, 文本, 应用程序&#10;&#10;描述已自动生成"/>\r\n

想了解有没有办法或者现成的软件,可以使得我复制的图片自动下载到剪切板(甚至会采用代理帮我自动翻墙下载)?
或者有什么浏览器复制的内容自带图片而不是图片链接?

自己顶一下

如果只是想把网页上的图文复制到 Word 中,可以这样做:选中网页中的图文后,不要复制,直接拖动到 Word 窗口中,图片就能正常显示了。

当然,本方法并未解决怎样把剪切板中的 URL 转换为图片的问题。

测试环境:

  • Chrome 129.0.6668.100
  • Word 2019
  • Windows 10 企业版 22H2

用脚本修改成word的剪切板式样行不行呢?

不清楚,或许有剪切板管理系统支持对剪切板内容进行替换。

1、我目前用的思源笔记在剪藏网页时候是把图标下载下来的
2、试试quicker呢,可以自动检测剪切板并做出一系列变化,比如剪切板变化、提取链接、下载图片存到本地,组合文本、写入剪切板。如果组合文本不支持图片,那就剪切板变化、提取链接、下载图片,等待按下某个键(自定义如shift)、粘贴链接之前文本-粘贴本地图片-粘贴链接之后文本-粘贴链接之前文本…

下载这个浏览器插件就好了,我一直用的这个,图片会变成真实图片(base64)而不是链接。
Webcollect - Helps capture webpages from web browser and save with Mybase (wjjsoft.com)

介绍

Webcollect 是一款网页浏览器扩展程序,可轻松截取网页内容。截取的内容可放入系统剪贴板,或直接使用Mybase Desktop保存, 无需先保存为 HTML 文件,然后手动插入。

好处和优势

  • Webcollect 允许您从网络浏览器中捕获整个或部分网页,并通过一次单击保存到 Mybase 数据库中,以供离线阅读或存档;
  • Webcollect 还允许您将整个或部分网页复制到系统剪贴板,然后您可以粘贴到任何您认为合适的地方;与网络浏览器的默认复制操作不同,通常只复制原始 HTML 文本而不复制图像数据,而 Webcollect 会尝试捕获整个网页并保留所有样式表和图像
  • 样式表、图像和 HTML 文本将嵌入到单个 .html 文件中,这有助于保持数据库和文件系统整洁。

关于软件

我知道有个软件可以实现复制图片,然后右键另存为。
PasteEx

关于复制图片

然后复制根本没那么复杂,就把这里改了就直接可以复制全文了。

思源的话,我是付费支持用户。
之前提过几个不是很重大,但是用起来别扭的feature改进,但是官方不太care。
我实在接受不了基本功能有问题的软件。

对了,我这是wps页面的截图。

尝试了一下Webcollect,不知道是否我的操作问题,无法copy图片
图像_2024-10-16_111212975.png

我目前的规避方法是:得先中转一手:

  1. 先贴到画笔或者IrfanView这样的图片软件里面,然后再从画笔/IrfanView拷贝到剪贴板
  2. 再到Word里面粘贴

毛线剪藏 可以一键选中网页内容导出 图片自动下载,高级功能完成度也很高,用了很久了

Edge-v116.0.1938.69-x64-Stable-with-1.5.1.exe - 蓝奏云
这里是一个旧版本Microsoft Edge浏览器,它带有web选择功能
web选择和截屏不一样哦,它能够原样复制网页中的图片、文字

用截图工具是不是就能满足你的需求

截图工具的话,图片会不清晰& 显著增大,肯定不如原图嘛