前提・実現したいこと
Ruby初心者ですが、
Rubyを使用して、ネットから株価情報を抜き出すシステムを作成しようとしております。
上場市場と売買株数を抜き出し、txtファイルとして保存したいです。
発生している問題・エラーメッセージ
txtファイルは作成されますが、中身は空のままです。
また、エラーメッセージなどは表示されておりません。
該当のソースコード
# coding: Windows-31J
require "open-uri"
# 日経の銘柄情報を取得し、銘柄リストを作るクラス
# 証券コード、上場市場、単元株数・売買単位が含まれる
class StockListMaker
attr_accessor :data_dir, :file_name
def initialize(market)
@market = market
@data_dir = "data"
@stock_info = []
end
# 銘柄情報の取得
def get_stock_info(code)
page = open_page(code)
return unless page
text = page.read.encode("Windows-31J" , :undef => :replace)
data = parse(text)
data[:code] = code
return unless data[:matket_section]
puts code
@stock_info << data
end
# 銘柄情報の保存
def save_stock_list
File.open(@data_dir + "/" + @file_name, "w") do |file|
@stock_info.each do |data|
file.puts [data[:code], data[:market_section], data[:unit]].join(",")
end
end
end
private
# 銘柄情報ページを開く
def open_page(code)
begin
open("http://www.nikkei.com" + "/nkd/company/?scode=#{code}")
rescue OpenURI::HTTPError
return
end
end
# HTMLから銘柄情報を抜き出す
def parse(text)
data = Hash.new
sections = []
reg_market = /option_mk" >([^< ]+) ?</
reg_unit = %r!<span class="m-stockInfo_detail_value">(\d|,)<span class="m-stockInfo_detail_unit"> 株</span>!
text.lines do |line|
if line = reg_market
sections << $+
elsif line =~ reg_unit
data[:market_section] = sections[0]
data[:unit] = get_unit($+)
return data
end
end
data
end
# 単元株数を得る
def get_unit(str)
if str == "---"
"1"
else
str.gsub(/,/,"")
end
end
end
# codeing: Windows-31J
require "B:/trade_simulator/lib/stocklistmaker"
# 東証銘柄リストを作る
slm = StockListMaker.new(:t)
slm.file_name = ARGV[0] || "tosho_list.txt"
puts slm.file_name
(1400..1402).each do |code|
slm.get_stock_info(code)
end
slm.save_stock_list
試したこと
parseメソッドのif end後(下から2つ目のendと3つ目のendの間)で
puts dataを実行すると、
{}
{}
{}
{}
{}
{}
{}
上記のような実行結果が返されます。
このことより、読み込んだデータを保管できていないのかと思っております。
エンコードのせいかと思い、coding:UTF-8でも試しましたが、ダメでした。
正規表現も見直しましたが、わかりませんでした。
補足情報(言語/FW/ツール等のバージョンなど)
・Ruby 2.3.3
・Eclipseプラットフォーム 4.6.3
-
気になる質問をクリップする
クリップした質問は、後からいつでもマイページで確認できます。
またクリップした質問に回答があった際、通知やメールを受け取ることができます。
クリップを取り消します
-
良い質問の評価を上げる
以下のような質問は評価を上げましょう
- 質問内容が明確
- 自分も答えを知りたい
- 質問者以外のユーザにも役立つ
評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。
質問の評価を上げたことを取り消します
-
評価を下げられる数の上限に達しました
評価を下げることができません
- 1日5回まで評価を下げられます
- 1日に1ユーザに対して2回まで評価を下げられます
質問の評価を下げる
teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。
- プログラミングに関係のない質問
- やってほしいことだけを記載した丸投げの質問
- 問題・課題が含まれていない質問
- 意図的に内容が抹消された質問
- 過去に投稿した質問と同じ内容の質問
- 広告と受け取られるような投稿
評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。
質問の評価を下げたことを取り消します
この機能は開放されていません
評価を下げる条件を満たしてません
質問の評価を下げる機能の利用条件
この機能を利用するためには、以下の事項を行う必要があります。
- 質問回答など一定の行動
-
メールアドレスの認証
メールアドレスの認証
-
質問評価に関するヘルプページの閲覧
質問評価に関するヘルプページの閲覧
checkベストアンサー
+1
# encoding: utf-8
require'open-uri'
require'certified'
def test(code)
data = open("http://www.nikkei.com/nkd/company/?scode=#{code}", &:read)
stock = data.scan(/<span class="m-stockInfo_detail_value\s*">(.+?)<span class="m-stockInfo_detail_unit"> 株/).flatten.first
market = data.scan(/<span class="m-company_data_select_btn .+?" data-tab=".m-company_data_option_mk" >(.+?)<\/span>/).flatten.first
[stock, market]
end
# =================================
# open('market.txt', 'w') do |f|
# f.puts(test('3197').join("\s"))
# end
# =================================
puts test('3197').join("\s") # => 10,152,600 東証1部
考えてみました。
補足
使い方
3193~3197の「上場市場と売買高」を取得してsample.txtに書き込む場合。
# encoding: utf-8
require'open-uri'
def test(code)
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\s*">(.+?)<span class="m-stockInfo_detail_unit"> 株/).flatten.first
[market, stock]
end
(3193..3197).each do |code|
open('sample.txt', 'a') do |f|
f.puts(test(code).join("\s"))
end
end
企業名と業界を追加したもの
# encoding: utf-8
require'open-uri'
def test(code)
data = open("http://www.nikkei.com/nkd/company/?scode=#{code}", &:read)
title, industry = data.scan(/<meta property="og:title" content="(.+?)"/).flatten[0].split(':').shift(2)
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\s*">(.+?)<span class="m-stockInfo_detail_unit"> 株/).flatten.first
[title, industry, market, stock]
end
(3193..3197).each do |code|
open('sample.txt', 'a') do |f|
f.puts(test(code).join("\t"))
end
end
実行結果例
鳥貴族[3193] 飲食店 東証1部 221,100
キリン堂ホールディングス[3194] 専門店・ドラッグストア 東証1部 51,600
ジェネレーションパス[3195] インターネットサイト運営 マザーズ 22,100
ホットランド[3196] 弁当・デリバリー 東証1部 47,000
すかいらーく[3197] 飲食店 東証1部 10,152,600
投稿
-
回答の評価を上げる
以下のような回答は評価を上げましょう
- 正しい回答
- わかりやすい回答
- ためになる回答
評価が高い回答ほどページの上位に表示されます。
-
回答の評価を下げる
下記のような回答は推奨されていません。
- 間違っている回答
- 質問の回答になっていない投稿
- スパムや攻撃的な表現を用いた投稿
評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。
15分調べてもわからないことは、teratailで質問しよう!
- ただいまの回答率 88.35%
- 質問をまとめることで、思考を整理して素早く解決
- テンプレート機能で、簡単に質問をまとめられる
2017/06/18 18:01
回答ありがとうございます。
頂いたコードを既存コードに追加し、
```ruby
# encoding: utf-8
require'open-uri'
require'certified'
中略
def open_page(code)
begin
data = open("http://www.nikkei.com/nkd/company/?scode=#{code}", &:read)
rescue OpenURI::HTTPError
return
end
end
def parse(text)
data = Hash.new
sections = []
reg_market = data.scan(/<span class="m-stockInfo_detail_value\s*">(.+?)<span class="m-stockInfo_detail_unit"> 株/).flatten.first
reg_unit = data.scan(/<span class="m-company_data_select_btn .+?" data-tab=".m-company_data_option_mk" >(.+?)<\/span>/).flatten.first
text.lines do |line|
if line = reg_market
sections << $+
elsif line =~ reg_unit
data[:market_section] = sections[0]
data[:unit] = get_unit($+)
return data
end
end
data
end
後略
```
と、してみましたが、
`require': cannot load such file -- certified (LoadError) といった形でrequireが上手く作動致しませんでした。
require'certified'をコメントアウトして再度実行したところ、 `get_stock_info': undefined method `read' for #<String:0x00000002274f00> (NoMethodError)と、何故かget_stock_infoメソッドのreadメソッドがエラーになりました。
調べてもよく分からなく、Rubyの最新バージョンに合う良い本も見つからず、せっかくお答え頂いたのに活用出来なく、大変申し訳ありません。
どうぞ、よろしくおねがいいたします。
2017/06/18 19:13 編集
なくても大丈夫なら無視していただいて構いません。
後からインストールするものなので何もしていなければ存在しません。
私のコードの使い方を追記しました。
2017/06/20 06:56
回答ありがとうございます。
h_a様のコードを実行してみましたが、invalid multibyte char (utf-8)とエラーが出たので調べてみたら、作成しているRubyファイルの文字コードがUTF-8ではありませんでした。
UTF-8として上書き保存し、実行した所、正常にsample.txtが作成され、情報も記載されておりました。
以上、ベストアンサーとさせて頂きます。
細かくお教えいただき、誠にありがとうございました。
2017/06/20 08:13