乐于分享
好东西不私藏

我把保存的网页变成了可编辑的文档,这个方法太好用了!

我把保存的网页变成了可编辑的文档,这个方法太好用了!

墨池有雨

读完需要

5

分钟

速读仅需 2 分钟

/ HTML转Markdown脚本分享 /

作为一个喜欢收集资料的人,我有个习惯——看到好文章就用 SingFile 扩展保存成 HTML。这样格式、图片、动图都能保留,看起来和原网页一模一样。

但问题是,这些 HTML 文件用起来特别不方便:

  • 想编辑整理?得在代码里扒拉

  • 想发给 AI 学习?HTML 标签太多干扰

  • 想在手机上看?加载慢还乱码

  • 想存到笔记软件?很多软件不支持 HTML

1

自己动手,解决问题

既然找不到现成的解决方案,我就自己写了个 Python 脚本。这个脚本能把 HTML 转换成 Markdown 格式,还能把网页里的图片下载到本地。

1.1

脚本的核心功能

简单说就是:HTML 文件进去,Markdown 文件出来,图片都在本地文件夹里

# 核心就是这个函数def html_to_md_with_local_images():    # 读取HTML    # 下载图片    # 转换成Markdown    # 保存结果

1.2

怎么处理图片?

这是最麻烦的部分,因为网页图片有好几种形式:

  1. 网络图片 – 有 http 开头的链接

  2. Base64 图片 – 直接嵌在 HTML 代码里

  3. 相对路径图片 – 只有文件名或相对路径

我的脚本都能识别并处理:

# 如果是网络图片,就下载if src.startswith('http'):    download_image(url)# 如果是Base64图片,就解码保存  if src.startswith('data:image'):    save_base64_image(data)# 其他情况也有相应处理

1.3

实际使用效果

转换前:文章.html + 一堆依赖文件转换后:文章.md + images/图片文件夹

Markdown 文件里图片引用是这样的:

![图片说明](./images/图片文件名.jpg)

2

怎么用这个脚本?

  1. 安装需要的库(一次性工作)

pip install beautifulsoup4 html2text requests
  1. 把你的 HTML 文件改名为 input.html

  2. 运行脚本

python html_to_md.py
  1. 得到结果

    • output.md – 转换后的 Markdown 文件

    • images/ – 所有图片都在这里

3

我用这个脚本做什么?

3.1

1. 整理技术文章

以前保存的技术文章,现在都能转成 Markdown,然后:

  • 放到 Obsidian 笔记里

  • 用 Typora 编辑整理

  • 分类存到不同文件夹

3.2

2. 给 AI 提供学习材料

现在给 AI 喂资料简单多了:

  • 直接把 Markdown 文件贴进去

  • AI 能看懂结构和内容

  • 不用再清理 HTML 标签

3.3

3. 在手机上看文章

把 Markdown 文件传到手机:

  • 用 Markdown 阅读器打开

  • 加载快,排版清晰

  • 图片都在本地,不用担心失效

4

一些实际经验

4.1

转换效果怎么样?

大部分网页转换效果都很好,特别是:

  • 博客文章、技术文档

  • 新闻、专栏文章

  • 论坛帖子

有些特别复杂的网页(比如整页都是 JavaScript 的),转换后可能需要微调。

4.2

图片会不会很大?

脚本会自动处理图片文件名,用 MD5 生成短文件名,避免重名。

如果网页图片很多,images文件夹可能会比较大。不过现在硬盘空间都够用,而且图片本地化后,再也不怕原网站删图了。

4.3

能不能批量处理?

当然可以,写个简单循环就行:

import osfor file in os.listdir('.'):    if file.endswith('.html'):        # 对每个HTML文件进行转换        convert_file(file)

5

我为什么推荐这个方法?

5.1

1. 一劳永逸

装好环境后,转换一篇文章只要几秒钟。

5.2

2. 完全控制

自己的脚本,想怎么改就怎么改:

  • 想调整转换规则?改几行代码

  • 想保存到不同位置?改输出路径

  • 想处理特定网站?加个特殊规则

5.3

3. 格式保留好

比直接复制粘贴强多了:

  • 标题层次保留

  • 列表格式正确

  • 代码块保持原样

  • 图片位置不变

6

可能遇到的问题

有的网页转换后格式乱了?

  • 试试调整 html2text 的参数

  • 或者换个 HTML 解析库

图片下载失败?

  • 脚本会跳过失败的图片继续转换

  • 可以在代码里加重试机制

转换速度慢?

  • 主要是下载图片耗时

  • 可以先把 HTML 里的图片链接批量处理

7

最后想说

现在我的知识库都是 Markdown 格式的,整理、搜索、分享都方便多了。

如果你也经常保存网页,然后又苦恼没法好好利用这些资料,可以试试这个方法。不一定非要用我的脚本,关键是要找到适合自己的信息处理流程。

工具的意义,就是让重复的事情自动化,把时间留给更重要的事。

源码

import re

import os

import base64

import hashlib

from urllib.parse import urlparse, unquote

from bs4 import BeautifulSoup

import html2text

import requests

##公众号:折耳猫的神奇口袋

def save_base64_image(base64_str, img_dir='images'):

    """保存base64编码的图片"""

    if not os.path.exists(img_dir):

        os.makedirs(img_dir)

    try:

        # 匹配base64图片格式

        match = re.match(r'data:image/(\w+);base64,(.*)', base64_str)

        if not match:

            return None

        img_format, data = match.groups()

        # 使用MD5生成唯一文件名

        filename = f"image_{hashlib.md5(data.encode()).hexdigest()[:8]}.{img_format}"

        filepath = os.path.join(img_dir, filename)

        # 解码并保存

        with open(filepath, 'wb') as f:

            f.write(base64.b64decode(data))

        return filename

    except Exception as e:

        print(f"保存base64图片失败: {str(e)}")

        return None

def save_url_image(url, img_dir='images'):

    """保存URL图片"""

    if not os.path.exists(img_dir):

        os.makedirs(img_dir)

    try:

        # 从URL中提取文件名

        parsed_url = urlparse(url)

        path = unquote(parsed_url.path)

        filename = os.path.basename(path)

        # 如果没有扩展名,添加jpg扩展名

        if not '.' in filename:

            filename = f"image_{hashlib.md5(url.encode()).hexdigest()[:8]}.jpg"

        # 确保文件名唯一

        counter = 1

        original_name, original_ext = os.path.splitext(filename)

        while os.path.exists(os.path.join(img_dir, filename)):

            filename = f"{original_name}_{counter}{original_ext}"

            counter += 1

        filepath = os.path.join(img_dir, filename)

        # 下载图片

        headers = {

            'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36'

        }

        response = requests.get(url, headers=headers, timeout=10)

        response.raise_for_status()

        # 保存图片

        with open(filepath, 'wb') as f:

            f.write(response.content)

        return filename

    except Exception as e:

        print(f"保存URL图片失败 {url}: {str(e)}")

        return None

def html_to_md_with_local_images(input_file='input.html', output_file='output.md', img_dir='images'):

    """将HTML转换为Markdown,并将图片保存在本地"""

    try:

        # 读取HTML文件

        with open(input_file, 'r', encoding='utf-8') as f:

            html_content = f.read()

        print(f"正在解析HTML文件...")

        # 使用BeautifulSoup解析HTML

        soup = BeautifulSoup(html_content, 'html.parser')

        # 创建图片目录

        if not os.path.exists(img_dir):

            os.makedirs(img_dir)

        # 查找所有图片

        img_tags = soup.find_all('img')

        print(f"找到 {len(img_tags)} 张图片")

        # 用于记录图片替换关系

        img_replacements = {}

        # 处理每张图片

        for i, img in enumerate(img_tags, 1):

            src = img.get('src', '')

            alt = img.get('alt', '') or f'图片{i}'

            if not src:

                print(f"跳过第 {i} 张图片(无src)")

                continue

            print(f"处理第 {i} 张图片: {src[:50]}...")

            filename = None

            # 判断图片类型并保存

            if src.startswith('data:image'):

                # base64图片

                filename = save_base64_image(src, img_dir)

            elif src.startswith('http://') or src.startswith('https://'):

                # 网络图片

                filename = save_url_image(src, img_dir)

            elif src.startswith('//'):

                # 协议相对URL

                filename = save_url_image('https:' + src, img_dir)

            else:

                # 相对路径或本地路径

                print(f"跳过第 {i} 张图片(不支持的类型)")

                continue

            if filename:

                # 创建Markdown图片格式

                md_img = f"![{alt}](./{img_dir}/{filename})"

                img_replacements[str(img)] = md_img

                print(f"  保存为: {filename}, MD格式: {md_img}")

            else:

                print(f"  保存失败")

        # 获取HTML文本

        html_text = str(soup)

        # 替换所有图片标签为Markdown格式

        for img_tag, md_img in img_replacements.items():

            html_text = html_text.replace(img_tag, md_img)

        # 创建自定义HTML转Markdown转换器

        class CustomHTML2Text(html2text.HTML2Text):

            def __init__(self):

                super().__init__()

                self.ignore_links = False

                self.ignore_images = True  # 我们已经手动处理了图片

                self.ignore_emphasis = False

                self.body_width = 0

                self.unicode_snob = True

                self.mark_code = True

            def handle_img(self, tag, attrs, start):

                # 跳过图片处理,因为我们已经替换为Markdown格式

                pass

        # 转换为Markdown

        converter = CustomHTML2Text()

        markdown_content = converter.handle(html_text)

        # 清理多余的空白行

        markdown_content = re.sub(r'\n{3,}', '\n\n', markdown_content)

        # 移除残留的HTML标签

        markdown_content = re.sub(r'<[^>]+>', '', markdown_content)

        # 写入输出文件

        with open(output_file, 'w', encoding='utf-8') as f:

            f.write(markdown_content)

        print(f"\n转换完成!")

        print(f"输入文件: {input_file}")

        print(f"输出文件: {output_file}")

        print(f"图片目录: {img_dir}/")

        print(f"共处理图片: {len(img_replacements)} 张")

        return markdown_content

    except FileNotFoundError:

        print(f"错误:找不到输入文件 '{input_file}'")

    except Exception as e:

        print(f"转换过程中出现错误: {str(e)}")

if __name__ == "__main__":

    html_to_md_with_local_images()

本站文章均为手工撰写未经允许谢绝转载:夜雨聆风 » 我把保存的网页变成了可编辑的文档,这个方法太好用了!

评论 抢沙发

5 + 7 =
  • 昵称 (必填)
  • 邮箱 (必填)
  • 网址
×
订阅图标按钮