2017-04-06 8 views
0

Webページを解析し、値を収集してデータベースに格納しようとしています。ここで関連するデータを解析してデータベースに値を格納する方法

はコメントアウトされたデータベース・コードと私のコードです:ここでは

require 'nokogiri' 
require 'open-uri' 

doc = Nokogiri::HTML(open("https://example.com/colors")) 
colors = doc.css(".colorCircle") 
colors_name = doc.css(".zw-m-c-txt")  

colors.each do |ele| 
    hex_code = ele.attr('style').split(";").first.split(":").last  

    colors_name.each do |name| 
     color_name = name.text 
     puts " ++++++ hex_code #{hex_code}" 
     puts " ++++++ color_name #{color_name}" 
     # color = colors.find_by(:hex_code => hex_code) 
     # if color.present? 
     #    color.update_attributes(:name => color_name) 
     #   else 
     #    model.colors.create(:name => color_name, :hex_code => hex_code) 
     #   end 
    end 
end 

は、HTMLソースページの詳細です:

<span class="colorCircle" style="background-color:#EEEFF4;"></span> 
<p class="zw-m-c-txt"> <span class="fnt-14"> White Orchid Pearl </span></p> 
<span class="colorCircle" style="background-color:#ACABB0;"></span> 
<p class="zw-m-c-txt"> <span class="fnt-14"> Modern Steel Metallic </span></p> 
<span class="colorCircle" style="background-color:#220909;"></span> 
<p class="zw-m-c-txt"> <span class="fnt-14"> Golden Brown Metallic </span></p> 
<span class="colorCircle" style="background-color:#43161b;"></span> 
<p class="zw-m-c-txt"> <span class="fnt-14"> Carnelian Red Pearl </span></p> 
<span class="colorCircle" style="background-color:#E8F1FA;"></span> 
<p class="zw-m-c-txt"> <span class="fnt-14"> Alabaster Silver </span></p> 

私が順次それをループすることができませんとに保存しますデータベース。ここでは、現在の出力は次のようになります。

++++++ color_name White Orchid Pearl 
++++++ hex_code #EEEFF4 
++++++ color_name White Orchid Pearl 
++++++ hex_code #ACABB0 
++++++ color_name White Orchid Pearl 
++++++ hex_code #220909 
++++++ color_name White Orchid Pearl 
++++++ hex_code #43161b 
++++++ color_name White Orchid Pearl 
++++++ hex_code #E8F1FA 
++++++ color_name Modern Steel Metallic 
++++++ hex_code #EEEFF4 
++++++ color_name Modern Steel Metallic 
++++++ hex_code #ACABB0 
++++++ color_name Modern Steel Metallic 
++++++ hex_code #220909 
++++++ color_name Modern Steel Metallic 
++++++ hex_code #43161b 
++++++ color_name Modern Steel Metallic 

これは予想される出力:私が期待される出力を取得し、色の名前でhex_codeに対応するデータベースに保存するにはどうすればよい

hex_code  #EEEFF4 
color_name White Orchid Pearl 
hex_code  #ACABB0 
color_name Modern Steel Metallic 
hex_code  #220909 
color_name Golden Brown Metallic 

?ここで

+0

したがって、各色の名前をスパンの背景色に関連付ける必要がありますか?例えば。ホワイトオーキッドパール#EEEFF4? – radubogdan

+0

2つのネストされたforループがあり、基本的には各色の各color_nameを実行していることに気づきます。 – radubogdan

+0

@radubogdanはい、あなたは正しいです、私は各色の名前をspanからのbkg-colorに関連づけたいと思います。 –

答えて

1

は、私はそのデータを望んでいた場合、私がしたいものです。

で使用し、
require 'nokogiri' 

doc = Nokogiri::HTML(DATA.read) 

data = doc.search('.colorCircle').map { |span| 
    hex = span['style'][/#([^;]+);$/, 1] 
    color = span.next_element.at('span').text.strip 
    [ hex, color ] 
}.to_h 
# => {"EEEFF4"=>"White Orchid Pearl", 
#  "ACABB0"=>"Modern Steel Metallic", 
#  "220909"=>"Golden Brown Metallic", 
#  "43161b"=>"Carnelian Red Pearl", 
#  "E8F1FA"=>"Alabaster Silver"} 

__END__ 
<span class="colorCircle" style="background-color:#EEEFF4;"></span> 
<p class="zw-m-c-txt"> <span class="fnt-14"> White Orchid Pearl </span></p> 
<span class="colorCircle" style="background-color:#ACABB0;"></span> 
<p class="zw-m-c-txt"> <span class="fnt-14"> Modern Steel Metallic </span></p> 
<span class="colorCircle" style="background-color:#220909;"></span> 
<p class="zw-m-c-txt"> <span class="fnt-14"> Golden Brown Metallic </span></p> 
<span class="colorCircle" style="background-color:#43161b;"></span> 
<p class="zw-m-c-txt"> <span class="fnt-14"> Carnelian Red Pearl </span></p> 
<span class="colorCircle" style="background-color:#E8F1FA;"></span> 
<p class="zw-m-c-txt"> <span class="fnt-14"> Alabaster Silver </span></p> 

data.each do |k, v| 
    puts "hex_code: %s\ncolor_name: %s" % [k, v] 
end 

なり出力:

hex_code: EEEFF4 
color_name: White Orchid Pearl 
hex_code: ACABB0 
color_name: Modern Steel Metallic 
hex_code: 220909 
color_name: Golden Brown Metallic 
hex_code: 43161b 
color_name: Carnelian Red Pearl 
hex_code: E8F1FA 
color_name: Alabaster Silver 

しかし、そこにありますこれらの団体と一緒にインターネット上のテーブル。 1つを解析してデータベーステーブルに挿入しようとするのではなく、値を抽出するためにデータベースにヒットする必要がないように、データを定数またはハッシュとして格納するモジュールまたはクラスを作成することをお勧めします。これらの値を使用してページ内の色を設定している場合や、色の値との相関を提示している場合でも、絶対に最速のアクセスが可能です。また、すでにレンダリングされている静的なページを作成することもできます。これらの関連付けと定義は変更されません。

データベースはいくつかの点で優れていますが、これは楽しい時期ではありません。


この

ele.attr('style').split(";").first.split(":").last 

は残酷です。

文字列から16進コードを抽出することは、文字列スライシングまたは正規表現に最適です。あなたはそれを複数の方法を行うことができます:

style = "background-color:#EEEFF4;" 

style.split(':').last.chop # => "#EEEFF4" 
style[-8..-2] # => "#EEEFF4" 
style[/(#\h{3,6});$/, 1] # => "#EEEFF4" 

スライス[-8..-2]を使用して、それは価値が色の六角形の値がである必要はありません。これは、常に6つの文字であると仮定しているため、おそらく最もエラーが発生しやすいです。 #FFFは、例えば#FFFFFFに相当します。したがって、3文字または6文字のバリアントを処理することが重要です。

上記の例では/#([^;]+);$/を使っていますが、/(#\h{3,6});$/と同じくらい簡潔ではありませんが、両方ともトレードオフがあるので、正規表現を使用する場合は選択してください。そして、彼らがどのように機能するかは、あなたが把握することです。すべてがゴールデン正規表現のハンマーでデータをヒットする機会ではないことを覚えておいてください。暗闇の扉を開いてバグの君主を導くことができるので、彼らが最高のツールであるときにそれらを使用してください。

そして、私は意図的に16進値の#を除外しました。それを追加すると、ルックアップやテーブルで冗長な文字にスペースが浪費されますが、あなたの走行距離は異なる場合があります。

+0

ありがとう@ theTinMan、非常に良い説明。 –

+0

あなたのコードは、もし私がDATA.readからデータを読み込んだ場合には動作しますが、私は次のエラーが出ます。

のブロック:未定義のメソッド 'at'がnilの場合:NilClass(NoMethodError) 'noticed that' span>には 'という次のタグは含まれません。だから私は検索 'data = doc.search( '。colorCircle、.zw-m-c-txt')で2つのクラスを指定しようとしました。あなたはどこが間違っているか教えてください。 –

+0

どこからデータを読んでいるのかわからないので、私はあなたを助けることはできません。 "[mcve]"は、使用した問題を示す質問に最小限の入力例が必要だと言っています。あなたが与えたHTMLが正確ではない可能性があります。コマンドラインで「nokogiri」を使用し、使用しているURLを渡すことをお勧めします。次に、探しているノードが見つかるかどうかを確認してください。ページがDHTMLを使用していて、ブラウザーだけがそれを見つけることができるかもしれません。応答のために –

関連する問題