まず、パーサー パッケージに次のメイン クラスを導入します。
Jsoup パーサーの入り口Facade は、一般的に使用される解析静的メソッドをカプセル化します。 maxErrors を設定してエラー レコードを収集できます。デフォルトは 0 で、収集しないことを意味します。関連クラスには、ParseError および ParseErrorList があります。この関数に基づいて、ページの構文をチェックして構文エラーを出力する PageErrorChecker を作成しました。
単一の字句解析結果を保存します。 Token は抽象クラスであり、その実装には Doctype、StartTag、EndTag、Comment、Character、および EOF が含まれており、6 つの字句タイプに対応します。
字句解析プロセスのステータスと結果を保存します。より重要な 2 つのフィールドは、state と EmitPending です。前者は状態を保存し、後者は出力を保存します。 2 番目に、tagPending/doctypePending/commentPending があり、完全に入力されていないトークンを保存します。
文字を読み取るロジックをカプセル化し、Tokenize 中の文字入力に使用されます。 CharacterReader には、NIO の ByteBuffer の Consumer()、unconsume()、mark()、rewindToMark() と同様の使用法と、高度な ConsumerTo() が含まれています。
列挙型を使用して実装された字句解析ステート マシン。
構文解析。トークンを通じて DOM ツリーを構築するクラス。
パーサー ステート マシン。
Token ベストで覆われていますが、実際にはクエリ時に使用され、選択部分に委ねられます。
次に、HTML の字句解析プロセスについて説明します。これは http://ued.ctrip.com/blog/?p=3295 の画像です。この画像では、タグ ラベルの状態転送プロセスが説明されています。
はここでは無視されます。 HTML コメント、エンティティ、および属性は、次の HTML のような基本的な開始/終了タグのみを保持します。
Jsoup の字句解析はより複雑です。そこから対応する部分を抽出して、次のようにしました。 miniSoupLexer (コードの一部はここでは省略されています。完全なコードはここにあります MiniSoupTokeniserState):
<div>test</div>
このプログラムを参照すると、Jsoup の字句解析の一般的な概念がわかります。アナライザー自体の作成は比較的面倒なプロセスであり、属性値 (一重引用符と二重引用符を区別する)、DocType、コメント、HTML エンティティ、およびいくつかのエラー条件が関係します。ただし、アイデアを理解した後は、コードの実装も段階的なプロセスになります。
enum MiniSoupTokeniserState implements ITokeniserState { /** * 什么层级都没有的状态 * ⬇ * <div>test</div> * ⬇ * <div>test</div> */ Data { // in data state, gather characters until a character reference or tag is found public void read(Tokeniser t, CharacterReader r) { switch (r.current()) { case '<': t.advanceTransition(TagOpen); break; case eof: t.emit(new Token.EOF()); break; default: String data = r.consumeToAny('&', '<', nullChar); t.emit(data); break; } } }, /** * ⬇ * <div>test</div> */ TagOpen { ... }, /** * ⬇ * <div>test</div> */ EndTagOpen { ... }, /** * ⬇ * <div>test</div> */ TagName { ... };}
次のセクションは構文解析部分から始まります。
最後に、私の Jsoup 解釈シリーズの記事とコード アドレスを示します:
https://github.com/code4craft/jsoup-learning