8.2. 介绍 sgmllib.py

HTML 处理分为三个步骤:将 HTML 分解成其组成部分,处理这些部分,然后将这些部分重新构建成 HTML。第一步由 sgmllib.py 完成,它是标准 Python 库的一部分。

理解本章的关键是要认识到 HTML 不仅仅是文本,而是结构化文本。结构源自开始标签和结束标签或多或少的层次序列。通常您不会以这种方式处理 HTML;您是在文本编辑器中以文本方式处理它,或者在 Web 浏览器或 Web 创作工具中以可视化方式处理它。sgmllib.py结构化方式呈现 HTML

sgmllib.py 包含一个重要的类:SGMLParserSGMLParserHTML 解析成有用的部分,例如开始标签和结束标签。一旦它成功地将一些数据分解成一个有用的部分,它就会根据它找到的内容调用自身上的一个方法。为了使用解析器,您需要继承 SGMLParser 类并重写这些方法。这就是我说它以结构化方式呈现 HTML 的意思:HTML 的结构决定了方法调用的顺序以及传递给每个方法的参数。

SGMLParserHTML 解析成 8 种数据,并为每种数据调用一个单独的方法

开始标签
一个开始块的 HTML 标签,例如 <html><head><body><pre>,或者一个独立的标签,例如 <br><img>。当它找到一个开始标签 tagname 时,SGMLParser 将查找一个名为 start_tagnamedo_tagname 的方法。例如,当它找到一个 <pre> 标签时,它将查找一个 start_predo_pre 方法。如果找到,SGMLParser 将使用标签属性列表调用此方法;否则,它将使用标签名称和属性列表调用 unknown_starttag
结束标签
一个结束块的 HTML 标签,例如 </html></head></body></pre>。当它找到一个结束标签时,SGMLParser 将查找一个名为 end_tagname 的方法。如果找到,SGMLParser 将调用此方法,否则它将使用标签名称调用 unknown_endtag
字符引用
一个由其十进制或十六进制等效值引用的转义字符,例如 &#160;。当找到时,SGMLParser 将使用十进制或十六进制字符等效值的文本调用 handle_charref
实体引用
一个 HTML 实体,例如 &copy;。当找到时,SGMLParser 将使用 HTML 实体的名称调用 handle_entityref
注释
一个 HTML 注释,包含在 <!-- ... --> 中。当找到时,SGMLParser 将使用注释的内容调用 handle_comment
处理指令
一个 HTML 处理指令,包含在 <? ... > 中。当找到时,SGMLParser 将使用处理指令的内容调用 handle_pi
声明
一个 HTML 声明,例如 DOCTYPE,包含在 <! ... > 中。当找到时,SGMLParser 将使用声明的内容调用 handle_decl
文本数据
一段文本。任何不属于其他 7 个类别的内容。当找到时,SGMLParser 将使用文本调用 handle_data
Important
Python 2.0 有一个错误,即 SGMLParser 根本无法识别声明(handle_decl 永远不会被调用),这意味着 DOCTYPE 会被静默忽略。这在 Python 2.1 中已修复。

sgmllib.py 附带了一个测试套件来说明这一点。您可以运行 sgmllib.py,在命令行上传递一个 HTML 文件的名称,它将在解析标签和其他元素时打印出来。它通过继承 SGMLParser 类并定义 unknown_starttagunknown_endtaghandle_data 和其他简单打印其参数的方法来实现这一点。

Tip
在 Windows 上的 ActivePython IDE 中,您可以在“运行脚本”对话框中指定命令行参数。使用空格分隔多个参数。

示例 8.4. sgmllib.py 的示例测试

以下是本书 HTML 版本目录中的一段代码。当然,您的路径可能会有所不同。(如果您尚未下载本书的 HTML 版本,您可以在 https://diveintopythonbook.pythonlang.cn/ 下载。)

c:\python23\lib> type "c:\downloads\diveintopython\html\toc\index.html"

<!DOCTYPE html
  PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
<html lang="en">
   <head>
      <meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
   
      <title>Dive Into Python</title>
      <link rel="stylesheet" href="diveintopython.css" type="text/css">

... rest of file omitted for brevity ...

通过 sgmllib.py 的测试套件运行它会产生以下输出

c:\python23\lib> python sgmllib.py "c:\downloads\diveintopython\html\toc\index.html"
data: '\n\n'
start tag: <html lang="en" >
data: '\n   '
start tag: <head>
data: '\n      '
start tag: <meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1" >
data: '\n   \n      '
start tag: <title>
data: 'Dive Into Python'
end tag: </title>
data: '\n      '
start tag: <link rel="stylesheet" href="diveintopython.css" type="text/css" >
data: '\n      '

... rest of output omitted for brevity ...

以下是本章其余部分的路线图

在此过程中,您还将学习 localsglobals 和基于字典的字符串格式化。