5.再次实现
鉴于SAX机制低级而简单,编写一个混合类来处理管理性细节通常很有帮助。这些管理性细节包括收集字符数据,管理布尔状态变量(如passthrough),将事件分派给自定义事件处理程序,等等。就这个项目而言,状态和数据处理非常简单,因此这里将专注于事件分派。
5.1.分派器混合类
与其在标准通用事件处理程序(如startElement)中编写长长的if语句,不如只编写自定义的具体事件处理程序(如start_page)并让它们自动被调用。你可以在一个混合类中实现这种功能,但通过继承这个混合类和ContentHandler来创建一个子类。
注意 混合类的功能有限,旨在与其它重要的类一起用作父类。
你希望程序具有如下功能。
再来说一下参数的问题。自定义处理程序(如start_foo)无需将标签名作为参数,而自定义默认处理程序(如default_start)需要这样做。另外,只有起始处理程序需要将属性作为参数。
一头雾水?先来编写这个类最简单的部分。
这里实现了事件的基本处理程序,他们只是调用方法dispatch,而dispatch将负责查找合适的处理程序,创建参数元素并使用这些参数调用处理程序。方法dispatch代码如下:
这个方法所做的工作如下。
(1)根据前缀('start'或'end')和标签名(如'page'),生成处理程序名称(如'start_page')。
(2)根据前缀生成默认处理程序的名称(如'default_start')。
(3)尝试使用getattr获取处理程序,并将默认值设置为None。
(4)如果结果是可调用的,就将args设置为一个空元组。
(5)否则,就尝试使用getattr获取默认处理程序,并将默认值也设置为None。另外,将args设置为一个只包含标签名的元组(因为默认处理程序只需要标签名)。
(6)如果要调用的是起始处理程序,就将属性添加到参数元组(args)中。
(7)如果获得的处理程序是可调用的(即为可行的具体处理程序或默认处理程序),就使用正确的参数调用它。
明白了吗?这大致意味着你现在可以像下面这样编写内容处理程序:
鉴于这个分派器混合类负责完成了大部分管理工作,因此内容处理程序非常简单、易于理解。当然,稍后我们将再添加一些功能。
5.2.将首部和尾部写入文件的方法以及默认处理程序
本节比前一节容易得多。我们将编写专门用于将首部和尾部写入文件的方法,而不在事件处理中直接调用self.out.write。这样就可以通过继承来轻松得重写这些方法。我们让将首部和尾部写入文件的方法尽可能简单。
在初次实现中,处理XHTML内容的代码还与处理程序耦合得太紧,现在它们将由default_start和default_end处理。
这些代码与前面相同,只是移到了独立的方法中。(这通常是件好事。)现在就余下最后一块拼图了。
5.3.支持目录
为创建必要的目录,需要使用函数os.makedirs,它在指定的路径中创建必要的目录。例如os.makedirs('foo/bar/baz')在当前目录下创建目录foo,再在目录foo下创建目录bar,然后在目录bar下创建目录baz。如果目录foo已经存在,将只创建目录bar和baz。同样,如果目录bar也已经存在,将只创建目录baz。然而,如果目录baz也已经存在,通常将引发异常。为避免出现这种情况,我们将关键字参数exist_ok设置为True。另一个很有用的函数是os.path.join,它使用了正确的分隔符(例如,在UNIX中为/)将多条路径合而为一。
在整个处理期间,都把当前目录路径存储在变量directory包含的目录名列表中。进入某个目录时,就将其名称附加到这个列表末尾;而离开这个目录时,就将其名称从目录列表中弹出。你可以定义一个函数,来确保当前目录已创建好。
请注意,将目录列表传递给os.path.join时,我使用了星号运算符*进行了参数拆分。
可通过将网站的根目录(如public_html)传递给构造函数,如下所示:
5.4.事件处理程序
终于要实现事件处理程序了。需要4个事件处理程序,其中两个用于处理目录,另外两个用于处理页面。目录处理程序只使用了列表directory和方法ensure_directory。
页面处理程序使用了方法write_header和write_footer。另外,他们还设置了变量passthrough(以便将XHTML代码直接写入文件),而且打开和关闭与页面相关的文件(这可能是最重要的)。
start_page的第一行代码看起来有点吓人,但与ensure_directory的第一行代码大致相同,只是加上了文件名(和扩展名.html)。
这个程序完整的源代码如图所示。
运行之后将生成如下文件和目录:
6.进一步探索
至此,你创建了一个基本程序,可以对其做哪些扩展呢?下面是一些建议。
本文分享自 Python机器学习算法说书人 微信公众号,前往查看
如有侵权,请联系 cloudcommunity@tencent.com 删除。
本文参与 腾讯云自媒体同步曝光计划 ,欢迎热爱写作的你一起参与!