🎄teratailクリスマスプレゼントキャンペーン2024🎄』開催中!

\teratail特別グッズやAmazonギフトカード最大2,000円分が当たる!/

詳細はこちら
スクレイピング

スクレイピングとは、公開されているWebサイトからページ内の情報を抽出する技術です。

Ruby

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

Webサイト

一つのドメイン上に存在するWebページの集合体をWebサイトと呼びます。

Ruby on Rails

Ruby on Railsは、オープンソースのWebアプリケーションフレームワークです。「同じことを繰り返さない」というRailsの基本理念のもと、他のフレームワークより少ないコードで簡単に開発できるよう設計されています。

HTML

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

Q&A

解決済

2回答

830閲覧

【Rails】Rakeタスクでのスクレイピングと普通のRubyで結果が異なる理由がわかりません。

s_eric

総合スコア184

スクレイピング

スクレイピングとは、公開されているWebサイトからページ内の情報を抽出する技術です。

Ruby

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

Webサイト

一つのドメイン上に存在するWebページの集合体をWebサイトと呼びます。

Ruby on Rails

Ruby on Railsは、オープンソースのWebアプリケーションフレームワークです。「同じことを繰り返さない」というRailsの基本理念のもと、他のフレームワークより少ないコードで簡単に開発できるよう設計されています。

HTML

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

0グッド

0クリップ

投稿2019/12/24 05:05

編集2019/12/24 05:26

前提・実現したいこと

Ruby on Rails でスクレイピングをして取得したデータをデータベースに格納するRakeタスクを作っています。

発生している問題・エラーメッセージ

まず、Rakeタスクを作る前に、単なるRubyでスクレイピングするプログラムを作りました。それを、Rakeタスクに移植して実行してみたのですが、出力されたデータが異なりました。
おそらく、スクレイピングで取得したHTMLが異なるのかと思うのですが、なぜ異なる結果が返されるのかがわかりません。これについてご教授いただけると幸いです。

該当のソースコード

以下のコードがまず始めにRubyで書いたものです。申し訳ないのですが、スクレイピングしているサイトのアドレスやCSSセレクタはダミーです。

Ruby

1require "mechanize" 2agent = Mechanize.new 3agent.user_agent = "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/79.0.3945.88 Safari/537.36" 4page = agent.get("https://example.com") 5 6price_list = [] 7item_list = [] 8 9replace = { 10 "\n" => "", 11 "\r" => "", 12 "\t" => "", 13 " " => "" 14} 15items = page.search("td.item") 16items.each do |d| 17 d = d.text 18 replace.each{|before, after| d.gsub!(before, after)} 19 item_list << d 20end 21 224.times do |i| 23 prices = page.search("table.price0#{i+1} td") 24 prices.each_with_index do |p, j| 25 next unless j % 10 == 0 26 price_list << p.text.gsub(/[^0-9]/,"").to_i 27 end 28end 29 30p item_list.zip(price_list).to_h

これをRakeタスクにしたものが以下です。

Ruby

1namespace :site do 2 desc "サイトから値段を取得" 3 4 task :get_prices => :environment do 5 prices = get_prices 6 p prices 7 p prices.length 8 end 9 10 def get_prices 11 agent = Mechanize.new 12 agent.user_agent = "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/79.0.3945.88 Safari/537.36" 13 page = agent.get("https://www.onamae.com/service/d-regist/price.html") 14 15 price_list = [] 16 item_list = [] 17 18 replace = { 19 "\n" => "", 20 "\r" => "", 21 "\t" => "", 22 " " => "" 23 } 24 items = page.search("td.item") 25 items.each do |d| 26 item = d.text 27 replace.each{|before, after| item.gsub!(before, after)} 28 item_list << item 29 end 30 31 4.times do |i| 32 prices = page.search("table.price0#{i+1} td") 33 prices.each_with_index do |p, j| 34 next unless j % 10 == 0 35 price_list << p.text.gsub(/[^0-9]/,"").to_i 36 end 37 end 38 39 item_list.zip(price_list).to_h 40 end 41end

試したこと

ユーザーエージェントがRailsか何かに書き換えられているのではと思い、明示的に指定するようしました。
Mechanizeのユーザーエージェントを変更する。=>変わらず

補足情報(FW/ツールのバージョンなど)

mechanize
Rails 6.0.1
ruby 2.6.3p62 (2019-04-16 revision 67580) [x86_64-darwin19]
Mechanize 2.7.6

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

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

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

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

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

otn

2019/12/24 05:11

どう異なるのでしょうか?
otn

2019/12/24 05:13

中間結果HTMLをファイルに書き出して、比較して調査してはどうでしょうか。
s_eric

2019/12/24 05:35

申し訳ありません。完全に説明不足でした。 上記の2つのコードでどちらもスクレイピングで得た商品名と商品名の価格を、ハッシュにして表示させています。どちらのコードでも、同じ内容のハッシュが出力されることを期待しているのですが、Rakeタスクでは、Ruby単体のプログラムの結果にはない、商品名と価格の組み合わせが含まれていました。 中間結果の書き出しですが、 file = File.open("tmp.html","w") file.puts(page.body) file.close というコードを挿入して、試したのですが、2つのコードのうちRuby単体のものではHTMLファイルが書き出されたのですが、Rakeタスクのほうではエラーも出ず、書き出されないという状況になっており、比較することができませんでした。
s_eric

2019/12/24 05:36

宜しくお願いいたします。
guest

回答2

0

自己解決

文字コードをASCII-8BITからUTF-8に変換することで、どちらも期待値が得られることがわかりました。
回答をくださった方々、ありがとうございました。

投稿2019/12/24 07:07

s_eric

総合スコア184

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

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

0

出力されたデータが異なりました。

標準出力のことでしょうか?
Rubyスクリプトは標準出力している箇所( puts とか pとか)がないように見えますが、具体的にどのように異なりますか?

投稿2019/12/24 05:17

ducci

総合スコア191

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

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

s_eric

2019/12/24 05:37

申し訳ありません。標準出力の箇所が抜けていたので、コードを訂正させていただきました。 ご教授いただければ幸いです。
ducci

2019/12/24 05:46

`p prices.length` の有無とかの差異ではなくですかね。
s_eric

2019/12/24 05:51

出力しているハッシュの内容の差異についてです。 具体的には上記の2つのコードでどちらもスクレイピングで得た商品名と商品の価格を、ハッシュにして表示させています。どちらのコードでも、同じ内容のハッシュが出力されることを期待しているのですが、Rakeタスクでは、Ruby単体のプログラムの結果にはない、商品名と価格の組み合わせが含まれていました。
ducci

2019/12/24 05:56

スクレイピング先のサイトが変更になった可能性とかはありませんかねー 何回試行しても、必ず出力が同じように異なるとかはありませんか?
s_eric

2019/12/24 06:02

どちらのコードもかなりの回数実行して内容を比べたのですが、いつもRakeタスクのほうに見慣れない主賓名と価格がセットされているという感じですね。 ブラウザで直接確認したのですが、その見慣れない商品名は見つけられなかったので、そもそもレスポンスされているHTMLがRakeタスクと純粋なRubyスクリプトで異なるのかなと考えている状況です。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.36%

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

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

質問する

関連した質問