chromium保存网页的功能是通过将DOM树序列化为html语言字符串的形式来实现的,它能够很好的将用户所看到的网页转换成一个html字符串。从WebCore::WebPageSerializerImpl::serialize函数可以看到整个流程。
大体思想是以document节点为起点,在WebPageSerializerImpl::buildContentForNode函数中递归序列化整棵DOM树。其中openTagToString序列化起始标签,endTagToString序列化结束标签,saveHTMLContentToBuffer添加字符流到buffer。总的来说结构还是非常清晰的。
但是,很遗憾。序列化的过程看似很好,实际上这样序列化生成的html文件浏览器却不一定能正确解析。因为DOM树本就不一定由一个html解析生成,其中间可能经过了无数js的各种加载,最终形成了我们所看到的网页。将DOM树序列化对于简单网页是足够的,但是对于一些复杂网页(比如百度音乐),这样序列化形成的html文件中包含很多错误的语法。比如字符串中包含标签,导致与真正的标签错误匹配。最终解析出来的是一堆乱码。
由此可以联想到appcache,appcache的功能也类似于保存网页,让用户可以离线浏览网页。它的特点是将资源都存在cache中,重复加载过程。这样就不会出现上述问题。但它也有不足之处,对于一些复杂网页,很难保存成用户看到的东西(比如用户对网页进行过一些操作,网页的结构已经改变);网页必须支持appcache;必须在加载时保存等。