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

问题描述:

我试图通过网页解析,收集值并将它们存储到数据库中。如何解析相关数据并将值存储到数据库

这里是我的代码注释的数据库代码:

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数据库?

+0

所以你想要将每个颜色名称与跨度的背景颜色关联起来?例如。白色兰花珍珠#EEEFF4? – radubogdan

+0

你意识到你有两个嵌套for循环,你基本上通过每个color_name运行每种颜色。 – radubogdan

+0

@radubogdan是的你是正确的,我想将每个颜色名称与span的bkg-color相关联。 –

这里就是我会做,如果我想这些数据:

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 

不过,也有当用于

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> 

其中,与这些协会互联网上的桌子。我建议找一个并创建一个将数据存储为常量或散列的模块或类,而不是解析一个并尝试将其注入到数据库表中,我建议找到一个模块或类,以便不必触击数据库即可提取值。如果您使用这些值设置页面颜色,或者即使您正在呈现值与颜色名称的相关性,也希望访问速度最快。或者创建一个已经呈现的静态页面,因为这些关联和定义不会改变。

数据库对于某些事情来说很棒,但对于它来说这似乎不是个好时机。


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});$/那么简洁,但是他们都有权衡,所以如果要使用正则表达式,请选择。他们的工作方式是让你弄清楚,只要记住,并非所有事情都有机会用金色正则表达式锤击数据;当他们是最好的工具时使用它们,因为它们可以打开黑暗的大门,迎来虫子的主宰。

而且,我特意排除在十六进制值#。添加它会浪费冗余字符上的空间以进行查找和表格,但是您的里程可能会有所不同。

+0

谢谢@theTinMan,非常好的解释。 –

+0

你的代码工作,如果我从DATA.read读取数据,但是如果我尝试直接从网络读取数据我得到以下error.'在

块:在'nil:NilClass(NoMethodError)'注意' span'只包含一行''它不包含下一个标签。所以我试着在搜索'data = doc.search('。colorCircle,.zw-m-c-txt')。map'中指定两个类,但仍然得到上面提到的错误。你能指导我哪里出错了吗? –

+0

我无法帮助你,因为我不知道你从哪里读取数据。 “[mcve]”表示在问题中您需要一个最小输入示例来演示我使用的问题,因此您提供的HTML可能不准确。我建议在命令行中使用'nokogiri'并将它传递给您正在使用的URL,然后查看您是否可以找到要查找的节点。它可能是页面使用DHTML,只有浏览器才能找到它。 –