web-dev-qa-db-ja.com

HTML本文コンテンツを抽出するための正規表現

XHTMLドキュメントのbodyタグの間からHTMLコンテンツを抽出できる正規表現ステートメントを探しています。

解析する必要があるXHTMLは非常に単純なファイルになるため、JavaScriptコンテンツや_<![CDATA[_タグなどについて心配する必要はありません。

以下は、私が解析しなければならないHTMLファイルの予想される構造です。処理する必要があるHTMLファイルのコンテンツをすべて正確に知っているので、このHTMLスニペットはユースケース全体をかなりカバーしています。この例の本文を抽出するための正規表現を取得できれば、私は幸せになります。

_<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
    "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
  <head>
    <title>
    </title>
  </head>
  <body contenteditable="true">
    <p>
      Example paragraph content
    </p>
    <p>
      &nbsp;
    </p>
    <p>
      <br />
      &nbsp;
    </p>
    <h1>Header 1</h1>
  </body>
</html>
_

概念的に、私はすべてに一致する正規表現文字列を作成しようとしましたが、内部の本文の内容に一致します。これにより、C#Regex.Split()メソッドを使用して本文のコンテンツを取得します。私はこの正規表現を考えました:

_((.|\n)*<body (.)*>)|((</body>(*|\n)*)
_

...トリックを実行しますが、RegexBuddyのテストコンテンツではまったく機能しないようです。

22
Matthew Ruston

これはうまくいくでしょうか?

((?:.(?!<body[^>]*>))+.<body[^>]*>)|(</body\>.+)

もちろん、次のように\s(スペースを含む要素)を考慮するために、必要な< body ...>を追加する必要があります。

((?:.(?!<\s*body[^>]*>))+.<\s*body[^>]*>)|(<\s*/\s*body\s*\>.+)

考え直してみると、なぜ否定的な先読みが必要だったのかわかりません...これも機能するはずです(整形式のxhtmlドキュメントの場合)。

(.*<\s*body[^>]*>)|(<\s*/\s*body\s*\>.+)
23
VonC

XHTMLは、正規表現よりもXMLパーサーを使用した方が簡単に解析できます。それはあなたがあなたが求めていることではないことを知っていますが、XMLパーサーはbodyノードにすばやく移動して、正規表現が与えるタグマッピングの問題なしにコンテンツを返すことができます。

編集:ここのコメントへの応答; XMLパーサーが遅すぎること。

XMLパーサーには2種類あります。1つはDOMと呼ばれ、大きくて重くて簡単で使いやすいものです。何かを行う前に、ドキュメントからツリーを構築します。もう1つはSAXと呼ばれ、高速かつ軽量で、作業量が多く、ファイルを順番に読み取ります。 SAXにBodyタグを検索させます。

DOMメソッドは複数の用途に適しています。タグをプルし、誰が子であるかを見つけます。 SAXパーサーはファイル全体を順番に読み取り、目的の情報をすばやく取得します。正規表現はSAXパーサーよりも高速ではありません。どちらも単純にファイルとパターンマッチをウォークスルーするためです。ただし、regexにはbodyタグが見つかった後、正規表現は検索を終了しません。 XMLの知識。実際、SAXパーサーはおそらく正規表現の小さな断片を使用して各タグを見つけます。

9
Karl
String toMatch="aaaaaaaaaaabcxx sldjfkvnlkfd <body>i m avinash</body>";
Pattern pattern=Pattern.compile(".*?<body.*?>(.*?)</body>.*?");
Matcher matcher=pattern.matcher(toMatch);
if(matcher.matches()) {
    System.out.println(matcher.group(1));
}
5
avinash
/<body[^>]*>(.*)</body>/s

と置換する

\1
3
Kev

なぜそれを分割できないのですか

</{0,1}body[^>]*> 

と2番目の文字列を取る?巨大な正規表現を探すよりもずっと速くなると思います。

3
bezmax

最初のbodyタグに一致:<\s*body.*?>

最後のbodyタグに一致:<\s*/\s*body.*?>

(注:タグの中央のスペースを考慮します。これは完全に有効なマークアップです)

このようにそれらを組み合わせると、ボディタグを含むすべての中間が得られます:<\s*body.*?>.*?<\s*/\s*body.*?>。また、改行を無視するSinglelineモードを使用していることを確認してください。

これはVB.NETで機能し、うまくいけば他の人でも機能します!

1
CrazyTim