如何解析相关数据并将值存储到数据库

How to parse related data and store the values to database

我正在尝试解析网页、收集值并将它们存储到数据库中。

这是我的代码,其中注释掉了数据库代码:

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      #EEEFF4
color_name    White Orchid Pearl 
hex_code      #ACABB0
color_name    Modern Steel Metallic
hex_code      #220909
color_name    Golden Brown Metallic

如何获得预期的输出并将其保存到与颜色名称 hex_code 对应的数据库中?

如果我想要这些数据,我会这样做:

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

但是,互联网上有 table 与这些关联。与其解析一个并尝试将其注入数据库 table,我建议您找到一个并创建一个模块或 class 将数据存储为常量或散列,这样您就不必点击数据库以提取值。如果您使用这些值来设置页面中的颜色,或者即使您要呈现这些值与颜色名称的相关性,您也希望获得绝对最快的访问速度。或者创建一个已经呈现的静态页面,因为这些关联和定义不会改变。

数据库在某些方面非常有用,但现在似乎不是做这件事的好时机。


这个

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

残忍。

从字符串中提取十六进制代码是字符串切片或正则表达式的一个很好的应用。您可以通过多种方式进行:

style = "background-color:#EEEFF4;"

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

使用切片 [-8..-2] 可能是最容易出错的,因为它假定值始终为六个字符长,而颜色的十六进制值则不必如此。例如,#FFF 等同于 #FFFFFF,因此处理三个或六个字符变体很重要。

在我上面的示例中,我使用了 /#([^;]+);$/,它不像 /(#\h{3,6});$/ 那样简洁,但它们都有权衡,所以如果您想使用正则表达式,请自行选择。它们的工作原理由您自己弄清楚,请记住,并非所有事情都是用正则表达式金锤敲击数据的机会;当它们是最好的工具时使用它们,因为它们可以打开黑暗之门并迎来虫子之王。

而且,我故意排除了十六进制值中的 #。添加它会浪费 space 用于查找和 table 的冗余字符,但您的里程可能会有所不同。