返回

HTML逆向生成Markdown -- Part 1

前端

序言

回想此前致力于将网页文章提取并转译为Markdown格式的Chrome插件构想,促成了“HTML逆向生成Markdown”项目的诞生。低估了解析难度的我,在耗费十余日后仅完成了一个半成品,遂决定暂时搁置。现将实现思路记录于此,待日后技艺精进再行完善。

解析过程可划分为四个阶段,现简要说明如下:

阶段一:解析HTML结构

  • 利用DOM解析器获取HTML结构
  • 识别并提取文章正文部分
  • 清理无用标记和冗余内容

阶段二:识别文本块

  • 将文章正文划分为段落、标题、列表等文本块
  • 对文本块进行语义分析,识别其类型和层级关系

阶段三:提取文本内容

  • 从文本块中提取纯文本内容
  • 处理特殊字符和转义序列
  • 移除不必要的空白和换行符

阶段四:生成Markdown语法

  • 根据文本块类型和层级关系,生成相应的Markdown语法
  • 添加必要的换行符和空白以提高可读性
  • 完成Markdown文档生成

需要注意的是,由于HTML的复杂性和多样性,解析过程可能存在挑战。例如,某些网站可能使用复杂的布局或动态加载技术,需要采取相应的策略来处理。

阶段一:解析HTML结构

以下是阶段一中使用的关键步骤:

  • 加载HTML内容: 使用外部库或内置函数加载HTML文档
  • 获取DOM结构: 将HTML文档解析为DOM树
  • 识别正文部分: 使用CSS选择器或特定算法识别文章正文所在的区域
  • 清理无用内容: 移除导航栏、侧边栏、页脚等无关内容

示例代码:

const cheerio = require('cheerio');

const html = '<html><body><div id="main-content">...</div></body></html>';
const $ = cheerio.load(html);

const mainContent = $('#main-content').html();

阶段二:识别文本块

在阶段二中,我们将采用以下步骤:

  • 划分子段落: 使用段落标记(

    )将正文划分为段落

  • *识别 ** 提取列表:**识别有序列表(
      )和无序列表(
        )及其子项
      • 语义分析: 对文本块进行语义分析以识别其类型和层级

      示例代码:

      const paragraphs = $('p');
      const headings = $('h1, h2, h3');
      const lists = $('ol, ul');
      

      阶段三:提取文本内容

      在阶段三中,我们将:

      • 提取纯文本: 从文本块中提取纯文本内容
      • 处理特殊字符: 将特殊字符(如&、<)转换为实体引用
      • 移除不必要内容: 移除不必要的空白和换行符

      示例代码:

      const text = paragraphs.text();
      text = text.replace(/&amp;/g, '&');
      text = text.replace(/&lt;/g, '<');
      

      阶段四:生成Markdown语法

      最后,在阶段四中,我们将:

      • *生成Markdown ** 生成Markdown段落:**生成Markdown段落(换行符+文本)
      • 生成Markdown列表: 生成Markdown列表(-、*、数字)
      • 完成Markdown文档: 将所有Markdown元素组合成完整的Markdown文档

      示例代码:

      const markdown = `# ${headings[0].text()}\n\n`;
      markdown += `${paragraphs.map(p => '- ' + p.text()).join('\n')}\n`;
      markdown += `${lists.map(l => '- ' + l.text()).join('\n')}`;
      

      结语

      虽然“HTML逆向生成Markdown”项目仍是一个半成品,但其思路和实现细节值得记录。期待在未来的某个时间点,能够将其完善为一个功能齐全的工具。