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ページで確認できます。
またクリップした質問に回答があった際、通知やメールを受け取ることができます。
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
回答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
- Ruby ドキュメント
- Tutorials - Nokogiri 鋸
- Nokogiri の基本(翻訳版) - Engine Yard Blog
- More Resources - Nokogiri 鋸
- Rubyによるクローラー開発技法 巡回・解析機能の実装と21の運用例
このNokogiri ライブラリを利用していて、Web ページの情報収集に向くMechanize というライブラリもあるようです
投稿2015/02/06 06:15
総合スコア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総合スコア241
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
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
総合スコア1679
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
あなたの回答
tips
太字
斜体
打ち消し線
見出し
引用テキストの挿入
コードの挿入
リンクの挿入
リストの挿入
番号リストの挿入
表の挿入
水平線の挿入
プレビュー
質問の解決につながる回答をしましょう。 サンプルコードなど、より具体的な説明があると質問者の理解の助けになります。 また、読む側のことを考えた、分かりやすい文章を心がけましょう。
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。