質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.48%
Ruby

Rubyはプログラミング言語のひとつで、オープンソース、オブジェクト指向のプログラミング開発に対応しています。

HTML

HTMLとは、ウェブ上の文書を記述・作成するためのマークアップ言語のことです。文章の中に記述することで、文書の論理構造などを設定することができます。ハイパーリンクを設定できるハイパーテキストであり、画像・リスト・表などのデータファイルをリンクする情報に結びつけて情報を整理します。現在あるネットワーク上のほとんどのウェブページはHTMLで作成されています。

Q&A

3回答

3895閲覧

Rubyの正規表現で特定のclassを持つ文字だけmatchさせたいです。

退会済みユーザー

退会済みユーザー

総合スコア0

Ruby

Rubyはプログラミング言語のひとつで、オープンソース、オブジェクト指向のプログラミング開発に対応しています。

HTML

HTMLとは、ウェブ上の文書を記述・作成するためのマークアップ言語のことです。文章の中に記述することで、文書の論理構造などを設定することができます。ハイパーリンクを設定できるハイパーテキストであり、画像・リスト・表などのデータファイルをリンクする情報に結びつけて情報を整理します。現在あるネットワーク上のほとんどのウェブページはHTMLで作成されています。

0グッド

0クリップ

投稿2015/02/06 04:55

lang

1<a href="/list/timeline/26527/latest" class="listName">欲しい文字</a><span class="date">(登録日:2014-12-03)</span><span class="red">(未読:1件)</span> 2 3<a href="/list/timeline/26527/latest" class="listName">欲しい文字</a><span class="date">(登録日:2014-12-03)</span> 4 5

<span class="red"</span>を持つグループだけを取得し、"欲しい文字"と(未読: x件)の部分を表示させたいのですが、どういった正規表現が正しいのでしょうか?

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答3

0

学習目的でなければ、正規表現ではなく 各言語にあるパーサ ライブラリを利用しましょう

Ruby であれば、nokogiri がそのひとつとして挙げられるでしょう

gem install nokogiri

例示されたコードをindex.html として保存しました

lang

1require 'nokogiri' 2 3file = File.read(File.expand_path('./index.html')) 4html = Nokogiri::HTML(file) 5 6p html.css('span.red').map { |element| element.text } 7# => ["(未読:1件)"]

Links

このNokogiri ライブラリを利用していて、Web ページの情報収集に向くMechanize というライブラリもあるようです

投稿2015/02/06 06:15

gouf

総合スコア2321

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

0

得られる HTML が間違いなく一行にお書きの要素が入っており、 class 要素の直後に > が来ていることを前提とします。
<span class="red"> が入っている行を取得するのは k.tada さんのやり方で良いと思います。

lang

1target = <<-EOF 2<a href="/list/timeline/26527/latest" class="listName">欲しい文字</a><span class="date">(登録日:2014-12-03)</span><span class="red">(未読:1件)</span> 3<a href="/list/timeline/26527/latest" class="listName">欲しい文字</a><span class="date">(登録日:2014-12-03)</span> 4EOF 5 6target.lines.select { |line| line.include?('class="red"') }

これにより文字列
<a href="/list/timeline/26527/latest" class="listName">欲しい文字</a><span class="date">(登録日:2014-12-03)</span><span class="red">(未読:1件)</span>

が含まれた配列が取得出来ました。
次にこの文字列から"欲しい文字"と"(未読: x件)"を取得するときに 正規表現を使う とすると
/class="listName">([^<]+).+class="red">([^<]+)/
で良いと思います。

合わせると

lang

1target.lines.select { |line| line.include?('class="red"') }.map do |line| 2 line.match(/class="listName">([^<]+).+class="red">([^<]+)/).to_a[1..-1] 3end 4#=> [["欲しい文字", "(未読:1件)"]]

となります。

しかし。
本当に、必ずそのような HTML が得られるでしょうか?
HTML に改行が入っていても Web ブラウザの解釈は同じになります。タグ内の要素が前後していてもやはり同じ解釈になります。
そのような HTML というものに対して正規表現で対応するのは、スイスアーミーナイフでマグロを捌こうとするようなもので、正直言って相応しくないと思います。

ということで、 HTML を処理する場合には HTML パーサを使いましょう。 gouf さんが示した Nokogiri や、Ruby 標準ライブラリの REXML が使えます(ただし今回のような HTML の一部だけに対しては REXML だとパース出来ません)。

では Nokogiri を使ってみます。
残念ながら元の HTML が a タグも span タグも並列に入っており、それらを覆う div タグが入っていないので、すこし面倒になります。具体的には <span class="red"> を選択した後に兄要素を取得する必要があります。 XPath ならば preceding-sibling を使います。 CSS では選択不可能でした(CSS4 で可能になるそうですが)。

HTML を少し変更して、それを対象にして実行します。

lang

1target = <<-EOF 2<a href="/list/timeline/26527/latest" class="listName">欲しい文字1</a><span class="date">(登録日:2014-12-03)</span><span class="red">(未読:3件)</span> 3<a href="/list/timeline/26527/latest" class="listName">欲しい文字2</a><span class="date">(登録日:2014-12-04)</span> 4<a href="/list/timeline/26527/latest" class="listName">欲しい文字3</a><span class="date">(登録日:2014-12-05)</span><span class="red">(未読:5件)</span> 5EOF 6 7doc = Nokogiri::HTML.parse(target) 8doc.xpath('//span[@class="red"]').map do |span| 9 [span.xpath('preceding-sibling::a[1]').text, span.text] 10end 11#=> [["欲しい文字1", "(未読:3件)"], ["欲しい文字3", "(未読:5件)"]]

あとは取得出来た配列の要素を何らかの方法で表示させれば良いでしょう。

投稿2015/02/06 08:39

編集2015/02/06 11:35
riocampos

総合スコア241

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

退会済みユーザー

退会済みユーザー

2015/02/18 23:15

わかりやすかったです。回答ありがとうございます!
guest

0

ざっと書いたので雑で申し訳ないですが、
下記のようにして、class="red"を含む行のみ抽出し、HTMLタグの中の文字のみを取り出して配列にしてみました。
あとはその配列から任意の項目を取り出してください。

lang

1target = <<-EOF 2<a href="/list/timeline/26527/latest" class="listName">欲しい文字</a><span class="date">(登録日:2014-12-03)</span><span class="red">(未読:1件)</span> 3<a href="/list/timeline/26527/latest" class="listName">欲しい文字</a><span class="date">(登録日:2014-12-03)</span> 4EOF 5 6target.lines.select {|l| l.include?('class="red"')}.each {|s| p s.scan(/>([^<]+)</) } # [["欲しい文字"], ["(登録日:2014-12-03)"], ["(未読:1件)"]]

投稿2015/02/06 05:30

k.tada

総合スコア1679

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

まだベストアンサーが選ばれていません

会員登録して回答してみよう

アカウントをお持ちの方は

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.48%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問