Jsoupコード解釈その6-パーサー(その2)_html/css_WEB-ITnose

WBOY
リリース: 2016-06-24 11:26:46
オリジナル
1343 人が閲覧しました

最近生活が少し忙しくて、いつも夜中に起きていて精神状態があまり良くありません。仕事もうまくいきません。アイデアはたくさんありますが、コードほどうまくいかないものもあります。忘れてください、私はまだ正しい姿勢を持っています。結局のところ、私の資格はまだ若いので、私は私の資格を続けます。

Jsoup のソース コードを読むのは退屈ではありません。結局のところ、パーサーもクローラーの重要なコンポーネントの 1 つです。コードを読んだ後、多くのことを得ることができ、HTML の知識も向上しました。

DOM ツリー生成処理

ここで TreeBuilder の部分を分けて構文解析処理と呼ぶのは少し不適切かもしれませんが、実際には Token に基づいて DOM ツリーを生成する処理です。このコンパイラでは。

TreeBuilder もファサード オブジェクトです。実際の構文解析は次のコードです。

protected void runParser() { while (true) { Token token = tokeniser.read();process(token);if (token.type == Token.TokenType.EOF) break; }}
ログイン後にコピー

TreeBuilder には、HtmlTreeBuilder と XmlTreeBuilder という 2 つのサブクラスがあります。 XmlTreeBuilder は当然、XML ツリーを構築するためのクラスです。実装は基本的にスタックを維持し、さまざまなトークンに従ってノードを挿入します。

@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;}
ログイン後にコピー

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;}
ログイン後にコピー

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>
ログイン後にコピー

ここで、HTML タグには 、 などのネスト要件があることがわかります。

を組み合わせて使用​​します。 Jsoup コードによると、HtmlTreeBuilderState が次のことを行うことがわかります:

文法チェック

たとえば、tr が table タグ内でネストされていない場合、構文エラーになります。以下のタグがInBody状態に直接出現するとエラーが発生します。 Jsoup でこの種のエラーが発生した場合は、トークン解析を見つけてエラーを記録し、直接終了せずに次のコンテンツの解析を続けます。

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; } }
ログイン後にコピー

タグの補完

たとえば、head タグが閉じられておらず、本文にのみ表示できるタグがいくつか書かれている場合、自動的に が閉じられます。 HtmlTreeBuilderState には、自動タグ補完を提供するメソッド anythingElse() があります。たとえば、InHead 状態の自動終了コードは次のとおりです。

private boolean anythingElse(Token t, TreeBuilder tb) { tb.process(new Token.EndTag("head")); return tb.process(t); }
ログイン後にコピー

次のようなタグ終了メソッドもあります。

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}
ログイン後にコピー

ケース スタディ

タグがなくなったらどうなりますか?

さて、パーサーのソース コードをたくさん読んだ後は、日常のアプリケーションに戻ったほうがよいでしょう。ページ上にさらに 1 つまたは 2 つの閉じられていないタグを記述するのが通常であることはわかっていますが、それらはどのように解析されるのでしょうか?

タグを例に挙げます:

  • 開始タグを忘れて終了タグだけを書きました
おめでとうございます、この
はエラーとして扱われるため、ページは間違いなくめちゃくちゃでした!もちろん、単に を追加しただけでは、何の影響もありません。 (タグが閉じられないようにするために、ページの一番下にもう少し を書くという話を誰かがしてくれたのを覚えています)

    開始タグを書きましたが、終了タグを見逃していました
分析しましょうこの状況はもう少し複雑です。内部にコンテンツをネストできないタグの場合、受け入れられないタグが見つかったときに閉じられます。
タグにはほとんどのタグを含めることができ、その場合、その有効範囲は HTML の最後まで続きます。

さて、パーサーシリーズの解析は終わりましたが、この期間でHTMLやステートマシンの内容はかなり勉強しましたが、実際に使うには程遠いです。まずは選択部分から始めましょう。これは日常的に使用する場合により意味があると思われます。

最後に、私の Jsoup シリーズのブログとソース コードのアドレスを添付します: http://github.com/code4craft/jsoup-learning

ソース:php.cn
このウェブサイトの声明
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。
人気のチュートリアル
詳細>
最新のダウンロード
詳細>
ウェブエフェクト
公式サイト
サイト素材
フロントエンドテンプレート