Table des matières
DOM树产生过程
HTML解析状态机
语法检查
标签补全
实例研究
缺少标签时,会发生什么事?
Maison interface Web tutoriel HTML Jsoup代码解读之六-parser(下)_html/css_WEB-ITnose

Jsoup代码解读之六-parser(下)_html/css_WEB-ITnose

Jun 24, 2016 am 11:26 AM

最近生活上有点忙,女儿老是半夜不睡,精神状态也不是很好。工作上的事情也谈不上顺心,有很多想法但是没有几个被认可,有些事情也不是说代码写得好就行的。算了,还是端正态度,毕竟资历尚浅,我还是继续我的。

读Jsoup源码并非无聊,目的其实是为了将webmagic做的更好一点,毕竟parser也是爬虫的重要组成部分之一。读了代码后,收获也不少,对HTML的知识也更进一步了。

DOM树产生过程

这里单独将TreeBuilder部分抽出来叫做语法分析过程可能稍微不妥,其实就是根据Token生成DOM树的过程,不过我还是沿用这个编译器里的称呼了。

TreeBuilder同样是一个facade对象,真正进行语法解析的是以下一段代码:

protected void runParser() { while (true) { Token token = tokeniser.read();process(token);if (token.type == Token.TokenType.EOF) break; }}
Copier après la connexion

TreeBuilder有两个子类,HtmlTreeBuilder和XmlTreeBuilder。XmlTreeBuilder自然是构建XML树的类,实现颇为简单,基本上是维护一个栈,并根据不同Token插入节点即可:

@Overrideprotected boolean process(Token token) { // start tag, end tag, doctype, comment, character, eof switch (token.type) { case StartTag: insert(token.asStartTag()); break; case EndTag: popStackToClose(token.asEndTag()); break; case Comment: insert(token.asComment()); break; case Character: insert(token.asCharacter()); break; case Doctype: insert(token.asDoctype()); break; case EOF: // could put some normalisation here if desired break; default: Validate.fail("Unexpected token type: " + token.type); } return true;}
Copier après la connexion

insertNode的代码大致是这个样子(为了便于展示,对方法进行了一些整合):

Element insert(Token.StartTag startTag) { Tag tag = Tag.valueOf(startTag.name()); Element el = new Element(tag, baseUri, startTag.attributes); stack.getLast().appendChild(el); if (startTag.isSelfClosing()) { tokeniser.acknowledgeSelfClosingFlag(); if (!tag.isKnownTag()) // unknown tag, remember this is self closing for output. see above. tag.setSelfClosing(); } else { stack.add(el); } return el;}
Copier après la connexion

HTML解析状态机

相比XmlTreeBuilder,HtmlTreeBuilder则实现较为复杂,除了类似的栈结构以外,还用到了HtmlTreeBuilderState来构建了一个状态机来分析HTML。这是为什么呢?不妨看看HtmlTreeBuilderState到底用到了哪些状态吧(在代码中中用 标明状态):

<!-- State: Initial --><!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"><!-- State: BeforeHtml --><html lang='zh-CN' xml:lang='zh-CN' xmlns='http://www.w3.org/1999/xhtml'><!-- State: BeforeHead --><head> <!-- State: InHead --> <script type="text/javascript"> //<!-- State: Text --> function xx(){ } </script> <noscript> <!-- State: InHeadNoscript --> Your browser does not support JavaScript! </noscript></head><!-- State: AfterHead --><body><!-- State: InBody --><textarea> <!-- State: Text --> xxx</textarea><table> <!-- State: InTable --> <!-- State: InTableText --> xxx <tbody> <!-- State: InTableBody --> </tbody> <tr> <!-- State: InRow --> <td> <!-- State: InCell --> </td> </tr> </table></html>
Copier après la connexion

这里可以看到,HTML标签是有嵌套要求的,例如,需要组合

来使用。根据Jsoup的代码,可以发现,HtmlTreeBuilderState做了以下一些事情:

语法检查

例如tr没有嵌套在table标签内,则是一个语法错误。当InBody状态直接出现以下tag时,则出错。Jsoup里遇到这种错误,会发现这个Token的解析并记录错误,然后继续解析下面内容,并不会直接退出。

InBody { boolean process(Token t, HtmlTreeBuilder tb) { if (StringUtil.in(name, "caption", "col", "colgroup", "frame", "head", "tbody", "td", "tfoot", "th", "thead", "tr")) { tb.error(this); return false; } }
Copier après la connexion

标签补全

例如head标签没有闭合,就写入了一些只有body内才允许出现的标签,则自动闭合。HtmlTreeBuilderState有的方法anythingElse()就提供了自动补全标签,例如InHead状态的自动闭合代码如下:

private boolean anythingElse(Token t, TreeBuilder tb) { tb.process(new Token.EndTag("head")); return tb.process(t); }
Copier après la connexion

还有一种标签闭合方式,例如下面的代码:

private void closeCell(HtmlTreeBuilder tb) { if (tb.inTableScope("td")) tb.process(new Token.EndTag("td")); else tb.process(new Token.EndTag("th")); // only here if th or td in scope}
Copier après la connexion

实例研究

缺少标签时,会发生什么事?

好了,看了这么多parser的源码,不妨回到我们的日常应用上来。我们知道,在页面里多写一个两个未闭合的标签是很正常的事,那么它们会被怎么解析呢?

就拿

标签为例:

  • 漏写了开始标签,只写了结束标签
case EndTag: if (StringUtil.in(name,"div","dl", "fieldset", "figcaption", "figure", "footer", "header", "pre", "section", "summary", "ul")) {  if (!tb.inScope(name)) { tb.error(this); return false; }  }
Copier après la connexion

恭喜你,这个会被当做错误处理掉,于是你的页面就毫无疑问的乱掉了!当然,如果单纯多写了一个,好像也不会有什么影响哦?(记得有人跟我讲过为了防止标签未闭合,而在页面底部多写了几个的故事)

  • 写了开始标签,漏写了结束标签

这个情况分析起来更复杂一点。如果是无法在内部嵌套内容的标签,那么在遇到不可接受的标签时,会进行闭合。而

标签可以包括大多数标签,这种情况下,其作用域会持续到HTML结束。

好了,parser系列算是分析结束了,其间学到不少HTML及状态机内容,但是离实际使用比较远。下面开始select部分,这部分可能对日常使用更有意义一点。

最后附上我的Jsoup系列博客及源码地址:http://github.com/code4craft/jsoup-learning

Déclaration de ce site Web
Le contenu de cet article est volontairement contribué par les internautes et les droits d'auteur appartiennent à l'auteur original. Ce site n'assume aucune responsabilité légale correspondante. Si vous trouvez un contenu suspecté de plagiat ou de contrefaçon, veuillez contacter admin@php.cn

Outils d'IA chauds

Undresser.AI Undress

Undresser.AI Undress

Application basée sur l'IA pour créer des photos de nu réalistes

AI Clothes Remover

AI Clothes Remover

Outil d'IA en ligne pour supprimer les vêtements des photos.

Undress AI Tool

Undress AI Tool

Images de déshabillage gratuites

Clothoff.io

Clothoff.io

Dissolvant de vêtements AI

AI Hentai Generator

AI Hentai Generator

Générez AI Hentai gratuitement.

Article chaud

R.E.P.O. Crystals d'énergie expliqués et ce qu'ils font (cristal jaune)
2 Il y a quelques semaines By 尊渡假赌尊渡假赌尊渡假赌
R.E.P.O. Meilleurs paramètres graphiques
2 Il y a quelques semaines By 尊渡假赌尊渡假赌尊渡假赌
R.E.P.O. Comment réparer l'audio si vous n'entendez personne
3 Il y a quelques semaines By 尊渡假赌尊渡假赌尊渡假赌

Outils chauds

Bloc-notes++7.3.1

Bloc-notes++7.3.1

Éditeur de code facile à utiliser et gratuit

SublimeText3 version chinoise

SublimeText3 version chinoise

Version chinoise, très simple à utiliser

Envoyer Studio 13.0.1

Envoyer Studio 13.0.1

Puissant environnement de développement intégré PHP

Dreamweaver CS6

Dreamweaver CS6

Outils de développement Web visuel

SublimeText3 version Mac

SublimeText3 version Mac

Logiciel d'édition de code au niveau de Dieu (SublimeText3)

Quel est le but du & lt; datalist & gt; élément? Quel est le but du & lt; datalist & gt; élément? Mar 21, 2025 pm 12:33 PM

L'article traite du HTML & lt; Datalist & GT; élément, qui améliore les formulaires en fournissant des suggestions de saisie semi-automatique, en améliorant l'expérience utilisateur et en réduisant les erreurs. COMMANDE COMPRES: 159

Quel est le but du & lt; Progress & gt; élément? Quel est le but du & lt; Progress & gt; élément? Mar 21, 2025 pm 12:34 PM

L'article traite du HTML & lt; Progress & GT; élément, son but, son style et ses différences par rapport au & lt; mètre & gt; élément. L'objectif principal est de l'utiliser & lt; Progress & gt; pour l'achèvement des tâches et & lt; mètre & gt; pour stati

Quel est le but du & lt; mètre & gt; élément? Quel est le but du & lt; mètre & gt; élément? Mar 21, 2025 pm 12:35 PM

L'article traite du HTML & lt; mètre & gt; élément, utilisé pour afficher des valeurs scalaires ou fractionnaires dans une plage, et ses applications courantes dans le développement Web. Il différencie & lt; mètre & gt; De & lt; Progress & gt; et ex

Quel est le but du & lt; iframe & gt; étiqueter? Quelles sont les considérations de sécurité lorsque vous l'utilisez? Quel est le but du & lt; iframe & gt; étiqueter? Quelles sont les considérations de sécurité lorsque vous l'utilisez? Mar 20, 2025 pm 06:05 PM

L'article traite du & lt; iframe & gt; L'objectif de Tag dans l'intégration du contenu externe dans les pages Web, ses utilisations courantes, ses risques de sécurité et ses alternatives telles que les balises d'objet et les API.

Quelle est la balise Meta de la fenêtre? Pourquoi est-ce important pour une conception réactive? Quelle est la balise Meta de la fenêtre? Pourquoi est-ce important pour une conception réactive? Mar 20, 2025 pm 05:56 PM

L'article traite de la balise Meta de la fenêtre, essentielle pour la conception Web réactive sur les appareils mobiles. Il explique comment une utilisation appropriée garantit une mise à l'échelle optimale du contenu et une interaction utilisateur, tandis que la mauvaise utilisation peut entraîner des problèmes de conception et d'accessibilité.

Comment utiliser les attributs de validation du formulaire HTML5 pour valider l'entrée utilisateur? Comment utiliser les attributs de validation du formulaire HTML5 pour valider l'entrée utilisateur? Mar 17, 2025 pm 12:27 PM

L'article discute de l'utilisation des attributs de validation de formulaire HTML5 comme les limites requises, motifs, min, max et longueurs pour valider la saisie de l'utilisateur directement dans le navigateur.

Quelles sont les meilleures pratiques pour la compatibilité entre les navigateurs dans HTML5? Quelles sont les meilleures pratiques pour la compatibilité entre les navigateurs dans HTML5? Mar 17, 2025 pm 12:20 PM

L'article examine les meilleures pratiques pour assurer la compatibilité des navigateurs de HTML5, en se concentrant sur la détection des fonctionnalités, l'amélioration progressive et les méthodes de test.

Comment utiliser le html5 & lt; time & gt; élément pour représenter les dates et les temps sémantiquement? Comment utiliser le html5 & lt; time & gt; élément pour représenter les dates et les temps sémantiquement? Mar 12, 2025 pm 04:05 PM

Cet article explique le html5 & lt; time & gt; élément de représentation sémantique de date / heure. Il souligne l'importance de l'attribut DateTime pour la lisibilité à la machine (format ISO 8601) à côté du texte lisible par l'homme, stimulant AccessIbilit

See all articles