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

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

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

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

正規表現

正規表現とは特定の文字列によるパターンマッチングを行う際に用いられる宣言型プログラミングです。

Q&A

解決済

2回答

360閲覧

Rubyの正規表現で複数マッチする中から特定の値を抜き出したい

Yc_Kz

総合スコア13

Ruby

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

正規表現

正規表現とは特定の文字列によるパターンマッチングを行う際に用いられる宣言型プログラミングです。

0グッド

0クリップ

投稿2017/07/01 18:36

###前提・実現したいこと

日経(http://www.nikkei.com/nkd/?MsgId=1)から株価の売買単価を取得し、
txtファイルとして保存したい

###該当のソースコード

Ruby

1 def test(code) 2 3 data = open("http://www.nikkei.com/nkd/company/?scode=#{code}", &:read) 4 5 market = data.scan(/<span class="m-company_data_select_btn .+?" data-tab=".m-company_data_option_mk" >(.+?)<\/span>/).flatten.first 6 stock = data.scan(/<span class="m-stockInfo_detail_value">([\d,]+)<span class="m-stockInfo_detail_unit"> 株/).flatten.first 7 8 [code, market, stock] 9 end

###困っていること
stockの正規表現(<span class="m-stockInfo_detail_unit"> 株)と一致する場所が3か所あり、
その中で売買単価だけを取得したい。

参考→view-source:http://www.nikkei.com/nkd/company/?scode=3193

###試したこと
①複数行に該当するよう変更

stock = data.scan(/<span class="m-stockInfo_detail_title">売買単位<\/span>.<span class="m-stockInfo_detail_value">([\d,]+)<span class="m-stockInfo_detail_unit"> 株/m).flatten.first

結果 → マッチせず

②stockを配列とし、3つ目に保管されているはずの売買単価を抜き出す

def test(code) stock = [] data = open("http://www.nikkei.com/nkd/company/?scode=#{code}", &:read) market = data.scan(/<span class="m-company_data_select_btn .+?" data-tab=".m-company_data_option_mk" >(.+?)<\/span>/).flatten.first stock = data.scan(/<span class="m-stockInfo_detail_value">([\d,]+)<span class="m-stockInfo_detail_unit"> 株/).flatten.first [code, market, stock[2]] end

結果

3193,東証1部,2 3194,東証1部,, 3195,マザーズ,5 3196,東証1部,1 3197,東証1部,4

調べてもよく分からなく、
分かる方はどうかお助けくださいませ。
###補足情報(言語/FW/ツール等のバージョンなど)
・Ruby 2.3.3
・Eclipseプラットフォーム 4.6.3

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

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

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

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

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

guest

回答2

0

ベストアンサー

scanはマッチ結果が配列で得られるので、3番目は添え字2です。firstを見ているのが間違い。

Ruby

1stock = data.scan(/<span class="m-stockInfo_detail_value">([\d,]+)<span class="m-stockInfo_detail_unit"> 株/).flatten[2]

Nokogiriなどでxpathで指定するなら、「textが"売買単位"であるspanの次のspan」とかでしょうか。
それだと「何番目」に依存しないので、ページのHTMLが多少変わってもずれません。

Ruby

1(前略) 2stock = doc.xpath("//span[text()='売買単位']/following-sibling::span/child::text()").text 3(後略)

前後はh_aさんの回答参照。

投稿2017/07/02 01:36

otn

総合スコア84423

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

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

Yc_Kz

2017/07/02 05:37

otn 様 度々、回答ありがとうございました。 firstを見ているのが間違いという事と、scanが配列でマッチ結果を得ている事から、コードを修正したら正常に取得されました。 今回はotn様の回答をペストアンサーとさせて頂きます。 誠にありがとうございました。
guest

0

Ruby

1# encoding: utf-8 2 3require 'open-uri' 4require 'certified' 5require 'nokogiri' 6 7def test(code) 8 url = "http://www.nikkei.com/nkd/company/?scode=#{code}" 9 data = Nokogiri::HTML.parse(open(url, &:read)) 10 11 market = data.xpath('//div[@class = "m-company_data_select_mk"]/span[1]').text 12 stock = data.xpath('//div[@class = "m-stockInfo_detail m-stockInfo_detail_right"]/ul/li[5]/span[2]').text 13 14 [code, market, stock] 15end 16 17(3193..3197).each do |code| 18 puts test(code).join(', ') 19end

実行結果例

3193, 東証1部, 100 株 3194, 東証1部, 100 株 3195, マザーズ, 100 株 3196, 東証1部, 100 株 3197, 東証1部, 100 株

考えてみました。
今回の場合は正規表現だとややこしくなるだろうと考えて
Nokogiriを使うことにしました。
Nokogiriについては付け焼刃なので詳しいことは分かりません。

投稿2017/07/01 20:14

編集2017/07/01 20:16
退会済みユーザー

退会済みユーザー

総合スコア0

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

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

Yc_Kz

2017/07/02 05:34

h_a 様 回答ありがとうございます。Nokogiriというライブラリがある事をそもそも知らず、勉強になりました。 改めて調べてみたいと思います。 回答ありがとうございました。
退会済みユーザー

退会済みユーザー

2017/07/02 09:49

どういたしまして。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.50%

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

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

質問する

関連した質問