HTML解析篇-浏览器

本文摘要说明现代浏览器是如何解析HTML的:

渲染引擎 Rendering engines

渲染引擎的职责就是渲染,即在浏览器窗口中显示所请求的内容。
默认情况下,渲染引擎可以显示html、xml文档及图片,它也可以借助插件(一种浏览器扩展)显示其他类型数据,例如使用PDF阅读器插件,可以显示PDF格式,将由专门一章讲解插件及扩展,这里只讨论渲染引擎最主要的用途——显示应用了CSS之后的html及图片。

主流程 The main flow

渲染引擎首先通过网络获得所请求文档的内容,通常以8K分块的方式完成。
下面是渲染引擎在取得内容之后的基本流程:

解析html以构建dom树->构建render树->布局render树->绘制render树

这里写图片描述

图2:渲染引擎基本流程

渲染引擎开始解析html,并将标签转化为内容树中的dom节点。接着,它解析外部CSS文件及style标签中的样式信息。这些样式信息以及html中的可见性指令将被用来构建另一棵树——render树。
Render树由一些包含有颜色和大小等属性的矩形组成,它们将被按照正确的顺序显示到屏幕上。
Render树构建好了之后,将会执行布局过程,它将确定每个节点在屏幕上的确切坐标。再下一步就是绘制,即遍历render树,并使用UI后端层绘制每个节点。
值得注意的是,这个过程是逐步完成的,为了更好的用户体验,渲染引擎将会尽可能早的将内容呈现到屏幕上,并不会等到所有的html都解析完成之后再去构建和布局render树。它是解析完一部分内容就显示一部分内容,同时,可能还在通过网络下载其余内容。

这里写图片描述

图3:webkit主流程

这里写图片描述

图4:Mozilla的Geoko 渲染引擎主流程

从图3和4中可以看出,尽管webkit和Gecko使用的术语稍有不同,他们的主要流程基本相同。Gecko称可见的格式化元素组成的树为frame树,每个元素都是一个frame,webkit则使用render树这个名词来命名由渲染对象组成的树。Webkit中元素的定位称为布局,而Gecko中称为回流。Webkit称利用dom节点及样式信息去构建render树的过程为attachment,Gecko在html和dom树之间附加了一层,这层称为内容接收器,相当制造dom元素的工厂。下面将讨论流程中的各个阶段。

HTML解析

跟HTML的变体XHTML不同,HTML更宽容,它允许忽略一些特定标签,有时可以省略开始或结束标签,这个特点让HTML的解析更加困难。

1.使用解析算法 The parsing algorithm进行符号化和构建树
符号化是词法分析的过程,将输入解析为符号,html的符号包括开始标签、结束标签、属性名及属性值。
符号识别器识别出符号后,将其传递给树构建器,并读取下一个字符,以识别下一个符号,这样直到处理完所有输入。
这里写图片描述

2.符号识别算法 The tokenization algorithm
基本示例——符号化下面的html:

<html>
<body>
Hello world
</body>
</html>

初始状态为“Data State”,当遇到“<”字符,状态变为“Tag open state”,读取一个a-z的字符将产生一个开始标签符号,状态相应变为“Tag name state”,一直保持这个状态直到读取到“>”,每个字符都附加到这个符号名上,例子中创建的是一个html符号。

当读取到“>”,当前的符号就完成了,此时,状态回到“Data state”,“”重复这一处理过程。到这里,html和body标签都识别出来了。现在,回到“Data state”,读取“Hello world”中的字符“H”将创建并识别出一个字符符号,这里会为“Hello world”中的每个字符生成一个字符符号。

这样直到遇到“”中的“<”。现在,又回到了“Tag open state”,读取下一个字符“/”将创建一个闭合标签符号,并且状态转移到“Tag name state”,还是保持这一状态,直到遇到“>”。然后,产生一个新的标签符号并回到“Data state”。后面的“”将和“”一样处理。
这里写图片描述
图10:符号化示例输入

3.树的构建算法 Tree construction algorithm
来看一下示例中树的创建过程:

<html>
<body>
Hello world
</body>
</html>

首先是“initial mode”,接收到html符号后将转换为“before html”模式,在这个模式中对这个符号进行再处理。此时,创建了一个HTMLHtmlElement元素,并将其附加到根Document对象上。
状态此时变为“before head”,接收到body符号时,即使这里没有head符号,也将自动创建一个HTMLHeadElement元素并附加到树上。
现在,转到“in head”模式,然后是“after head”。到这里,body符号会被再次处理,将创建一个HTMLBodyElement并插入到树中,同时,转移到“in body”模式。
然后,接收到字符串“Hello world”的字符符号,第一个字符将导致创建并插入一个text节点,其他字符将附加到该节点。
接收到body结束符号时,转移到“after body”模式,接着接收到html结束符号,这个符号意味着转移到了“after after body”模式,当接收到文件结束符时,整个解析过程结束。
这里写图片描述

步骤就是先生成HTML解析符号,再将符号构建成Element树

CSS解析

未完待续…

<!DOCTYPE html>
<html>
 <head>
  <meta http-equiv="content-type" content="text/html;charset=utf-8" />
 </head>
 <body>
    <!-- 诗词展示 -->
      <div style="font-family: msyh;text-align: center;">

        <h2>早发白帝城</h2>
        <div style="padding: 20px 20px; background-color: rgb(250, 192, 143);font-family: simkai;">
          朝辞白帝彩云间,千里江陵一日还。<br />
          两岸猿声啼不住,轻舟已过万重山。<br />
        </div>

        <h2>赠汪伦</h2>
        <div style="padding: 20px 20px; background-color: rgb(250, 192, 143);font-family: simkai;">
          李白乘舟将欲行,忽闻岸上踏歌声。<br />
          桃花潭水深千尺,不及汪伦送我情。<br />
        </div>

        <h2>望庐山瀑布</h2>
        <div style="padding: 20px 20px; background-color: rgb(250, 192, 143);font-family: simkai;">
            日照香炉生紫烟,遥看瀑布挂前川。<br />
              飞流直下三千尺,疑是银河落九天。<br />
          </div>
  </div>

  <!-- 古词释义 -->
    <div style="text-shadow: 5px 5px 5px #787878;color: #fff;background-color: #CDC9C9;">
      <p><span style="margin-right: 10px;"></span>发:启程。白帝城:故址在今重庆市奉节县白帝山上。</p>
      <p><span style="margin-right: 10px;"></span>踏歌:唐代民间流行的一种手拉手、两足踏地为节拍的歌舞形式,可以边走边唱。</p>
      <p><span style="margin-right: 10px;"></span>桃花潭:在今安徽泾县西南一百里。《一统志》谓其深不可测。深千尺:诗人用潭水深千尺比喻汪伦与他的友情,运用了夸张的手法。</p>
    </div>


 </body>
</html>
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值