HTMLタグの中味抽出について

このQ&Aのポイント
  • HTMLのタグの中味を抽出する正規表現について学んだが、その動作原理に疑問がある。
  • 処理対象の文字列が末尾の > より前の部分となるのではないかと考えたが、実際の結果と異なる。
  • 正規表現の動作原理を正確に理解するため、詳しい説明を求めている。
回答を見る
  • ベストアンサー

HTMLタグの中味抽出

HTMLのタグの中味を抽出する正規表現として、以下の形を学びました。 [^<]+?(?=>) この正規表現で以下のHTML文を処理すると、 <tag_nakami_1><tag_nakami_2>title_text</tag_nakami_1></tag_nakami_2> 以下の結果が出ました。 tag_nakami_1 tag_nakami_2 /tag_nakami_1 /tag_nakami_2 ですが、なぜ、「title_text」の部分がうまく取り除かれたのかがわかりません。 <tag_nakami_1><tag_nakami_2> まで処理がすんで、次は title_text</tag_nakami_1> が処理対象の文字列となるのでは無いでしょうか?その場合、末尾の > より前の部分、title_text</tag_nakami_1 から < のみが除かれた文字列、title_text/tag_nakami_1 が抽出される、つまり以下のような結果が出そうに思えます。 tag_nakami_1 tag_nakami_2 title_text/tag_nakami_1 /tag_nakami_2 ですが実際はそうなりません。 これはなぜなのでしょうか……。

質問者が選んだベストアンサー

  • ベストアンサー
  • y_shimizu
  • ベストアンサー率41% (27/65)
回答No.1

言葉で説明しにくいのですが、 (1)[^<] → <じゃない文字 (2)+? →直前の文字繰り返し (3)(?=>) → 次が> なので <tag_nakami_1><tag_nakami_2>title_text</tag_nakami_1> の<tag_nakami_2>までマッチしたら、 次は t を見る、(1)に合致するので、マッチしてるかもしれない文字列はt 次は i を見る、(1)に合致するので、マッチしてるかもしれない文字列はti これをtitle_textまで繰り返して 次は < を見る、(1)に合致しないので、マッチしてるかもしれない文字列はクリア 次は / を見る、(1)に合致するので、マッチしてるかもしれない文字列は/ これをtag_nakami_1まで繰り返して 次は > を見る、(3)に合致するので、マッチここまでの文字列 /tag_nakami_1 はマッチしている みたいなかんじです。

wine38
質問者

お礼

ご説明ありがとうございました。 正規表現の処理の仕方をちゃんと理解していなかったんですね、私は……。 てっきり、「先読みの条件までの文字列全体」を抽出してそれに対して処理を加えるものだと思い込んでいましたが、正規表現自体は文字列全体が何であるかは知らず、あくまで前から一文字ずつ条件に合致するかを見ていき、条件に合わない箇所が出たらそこまでの処理結果は破棄する、ということなのですね。 目からウロコが落ちました。 ありがとうございました!

関連するQ&A

  • HTMLタグ内文字を抽出するには

    HTMLタグ内の特定<title>タグ内文字列のみをエクセルマクロで抽出する方法はありますか? またエクセルのURL一覧の横に結果を表示させたいです。 宜しくお願い致します。

  • RubyのHTMLパーサーで複数のタグを抽出したい

    現在、Rubyを用いて あるWebページから特定のタグの要素を抽出して テキストデータに出力したいと思い、プログラムを書いているのですが、 途中で行き詰ってしまいました。 ちなみにHpricotやNokogiriといったHTMLパーサーを試してみました。 パーサーを使うのは初めてです。 例えば以下のようにHTML文書に抽出したい部分がDIVタグとPタグに囲まれていた場合、 ===================================== ・・・ <div class="content"> <div class="header">不要部分</div> <div class="title">抽出したい文字列1</div> <div class="subtitle">抽出したい文字列2</div> <div class="subtitle">抽出したい文字列3</div> <p class="paragraph">抽出したい文字列4</p> <p class="paragraph">抽出したい文字列5</p> <div class="comment">抽出したい文字列6</div> <div class="footer">不要部分</div> </div> ・・・ ===================================== このHTMLからまずは 抽出したい文字列1 抽出したい文字列2 抽出したい文字列3 抽出したい文字列4 抽出したい文字列5 抽出したい文字列6 といった出力が得たいのです。 プログラムも書いてみました。 ===================================== #ドキュメント全体を取得(dataにはHTMLの文字列が入っている) html = Hpricot(data) #内容部分(contentクラスのdiv)を取得(CSSセレクタで記述) content = html/"div.content" ===================================== ここまでは良いのですが、 そのあと、div要素を取り出すだけであれば headerクラスと、footerクラスを抽出しないように ===================================== (content/"div:not(.header):not(.footer)").each{ |line| puts line.inner_html } ===================================== とすることで、 抽出したい文字列1 抽出したい文字列2 抽出したい文字列3 抽出したい文字列6 が得られますが、pタグをカンマでdivの前に追加して ===================================== (content/"p,div:not(.header):not(.footer)").each{ |line| puts line.inner_html } ===================================== のようにすると、 抽出したい文字列4 抽出したい文字列5 抽出したい文字列1 抽出したい文字列2 抽出したい文字列3 抽出したい文字列6 のように出力されます。 同様にdivの後にpを追加し ===================================== (content/"div:not(.header):not(.footer),p").each{ |line| puts line.inner_text } ===================================== のようにすると 抽出したい文字列1 抽出したい文字列2 抽出したい文字列3 抽出したい文字列6 抽出したい文字列4 抽出したい文字列5 のようになってしまいます。 つまり、複数のタグを指定すると、指定した順序で抽出されるようです。 代わりに子供すべてを列挙するchildのようなものがあるかと、調べてみたのですが、 どうやらそのような書き方はないようです。 複数のタグを含む場合にはHTMLパーサーでは解析できないのでしょうか。 パーサーは抽出時に順番を保証はしてくれないのでしょうか。 あきらめて、正規表現で抽出しようと思いましたが、 ===================================== <div class="comment"> <div class="comment_header">ごちゃごちゃ</div> <div class="comment_body">抽出したい要素6</div> </div> ===================================== などDIVが入れ子となっている場合に、 非常にややこしく感じたので お手上げ状態です。 どのように、解決できるでしょうか。 よろしくお願いします。

    • ベストアンサー
    • Ruby
  • VBAを使ってHTMLソースから特定の文字列を抽出したいと思っています

    VBAを使ってHTMLソースから特定の文字列を抽出したいと思っています。 正規表現を利用してタグに挟まれた文字を抽出したいのですがうまくいきません。 タグごと抽出する方法でも構わないので教えてください。 例えば <a href="www.yahoo.com△">○○○</a>   ・・・<1> ※△は(www.yahoo.com)+(半角数字1文字) ※○○○は1文字以上の全角文字 このようなパターンの文字列(<1>を丸ごと)を抜き出すには どのような正規表現を書けばよいでしょうか? 単に<a href ではじまって </a>  で終わる文字列であれば <a href.*</a> で良いと思うのですが、もう少し範囲を絞れば目的の文字列だけを抽出できるので ぜひ実現させたいと思っています。宜しくお願いします。

  • タグを正規表現で完全に削除

    こんばんわ~ときどきこちら様でお世話になってます タグ(Java ScriptやHTML中のCSS等きわめて複雑なものも含む)を完全に削除してウェブサイトの文字だけを抜き出したいんですけど自分にはハードルが高すぎたみたいです^^; http://www.din.or.jp/~ohzaki/perl.htm#HTML_Tag いろいろ調べているうちにこちらのサイト様を発見し、 $none_tag =~ s/$tag_regex//; とやってみましたがなぜかタグが残ってしまいます。 とあるサイトの【文字】だけを抜き出せれば良いのでタイトルに正規表現と記載しましたがその他の方法でも構いませんのでよろしくお願いしますm(_ _)m

    • ベストアンサー
    • Perl
  • Perlの正規表現で文字の抽出

    Perlを勉強しているのですが正規表現についてよくわからないので教えてください。 $text="【件名】本文" とあるときに、【】で囲まれた文字列(【】も含む)を抽出し、$textに戻したいのですがどうすればいいのでしょうか? ($textの中身を【件名】としたいのです) よろしくお願いします。

    • ベストアンサー
    • Perl
  • phpのHTMLからのRSS linkタグ抽出

    こんにちは phpを使ってrssを配信している サイトのhtmlデータを取得し、 rssのリンクが書いてある<link>タグを抽出しようとしています。 preg_matchなどを使った抽出の時に使っている正規表現は一応、 |.*<link rel=[\"\']alternate[\"\'](.*rss.*xml.*)?>|s なのですが、上記のrss xmlという文字列の順序や、 rssのバージョンを考えずに取得できる方法、 タグ内の他の属性値、属性値の順序など、 人によって書き方が異なり、 取得が難しいです。 これ以外の、より簡単な取得方法や、抽出におけるよい正規表現を知っておられる方、 どうか抽出方法を教えていただけませんでしょうか?

  • getAttributeによるHTMLのタグ抽出について

    web上にあるHTMLで書かれた文書から、タグ別に抽出しようと思っています。以下にあるのはプログラムの一部です。 <a href~のタグだときちんと抽出できるのですが、<img src~から始まるタグでは抽出できなかったのです。どこがいけないのでしょうか? よろしくお願いします。 . . . public void handleStartTag(HTML.Tag tag, MutableAttributeSet attr, int pos) { if (tag.equals(HTML.Tag.A)) { href[i] = (String) attr.getAttribute(HTML.Attribute.HREF); i++; } else if (tag.equals(HTML.Tag.IMG)) { src[j] = (String) attr.getAttribute(HTML.Attribute.SRC); j++; } else { } } . . .

    • ベストアンサー
    • Java
  • HTML形式のメールからテキストのみを抽出したい

    HTML形式の本文からHTMLのタグを除去して、プレーンテキストのみを抽出するプログラムを作成していますが、うまく処理ができなくて困っています。 使用言語はperl,HTML::Parserを使用してプログラムを作成したいと考えています。 日本語の本文のテキスト抽出を行っているのですが、 うまく抽出できるものと文字化けするものがあります。 nkfモジュールを使用すれば解決できそうだと考え、試行錯誤しておりますが、うまく処理できていません。 perlテキスト処理に詳しい方がいらっしゃいましたら、 教えてください。 よろしくお願いいたします。

  • 正規表現でHTMLタグの属性まで選んで抽出

    現在、掲示板をPHPで作っています。 入力された文字列の無効化と許可タグの分別に正規表現を使いたいと考えております。 そこで、現状では、まずすべての < > を特殊文字に変換し、その後に、許可タグ(属性)のタグを < > にもどそうとしています。 たとえば、fontタグならcolorとsizeを許可しようとして、次のような正規表現を作ってみましたが、うまくいきません。 /&lt;font((( )*(color=)[\"\']?.{1,7}[\"\']?)|(( )*(size=)[\"\']?.{1,2}[\"\']?))*&gt;/i 正規表現はまだ勉強し始めたところで、おかしなところだらけだと思いますが、何かヒントだけでもいただけたらと思います。 どうぞよろしくお願いします。

    • ベストアンサー
    • PHP
  • jQueryの.text()関数でiframe

    .text()でHTMLの中の文字列を取得してるんですが これはHTMLタグを取り除いてテキストのみを抽出するものだと思っていたら <iframe から始まる場合はそのまま<iframe~と取ってきてしまいます。 これを回避する方法はありませんか? やはり取ったあとで<iframe~の部分を正規表現で取り除くしかないのでしょうか。 よろしくおねがいします。

専門家に質問してみよう