首页 > 解决方案 > 如何使用 Ruby 解析 HTML 文件标题

问题描述

我有一个要在 Ruby 中解析的 HTML 文件。HTML 文件非常简单,只包含标题、链接和段落。我正在使用 Nokogiri 进行解析。

我正在处理的 HTML 文件的一个示例是:

<h1><a id="Dog_0"></a>Dog</h1>
<h2><a id="Washing_dogs_3"></a>Washing Dogs</h2>
<h3>Use soap</h3>
<h2><a id="Walking_dogs_1"></a>Walking Dogs</h2>

我需要将h1标题视为父项,将h2标题视为h1其所在h3标题的子项,将标题视为其所在标题的子项h2,等等。

我想将此信息存储在哈希数组中,这样

[ { 
   h1: "Dog",
 link: "Dog_0",  
},{
   h1: "Dog",
   h2: "Washing Dogs",
   link: "Dog_0#Washing_dogs_3"
},{
   h1: "Dog",
   h2: "Washing Dogs",
   h3: "Use Soap",
   link: "Dog_0#Washing_dogs_3"
},{
   h1: "Dog",
   h2: "Walking Dogs"
   link: "Dog_0#Walking_dogs_1"
}]

由于没有节点是嵌套的,我认为我不能使用任何有用的方法来查找子节点。到目前为止,我所拥有的是:

array_of_records = []; #Store the records in an array
desired_headings = ['h1','h2','h3','h4','p'] # headings used to split html into records

Dir.glob('*.html') { |html_file|


  nokogiri_object = File.open(html_file) { |f| Nokogiri::HTML(f, nil, 'UTF-8') }

  nokogiri_object.traverse { |node|
   next unless desired_headings.include?(node.name)
   record = {}
   record[node.name.to_sym] = node.text.gsub(/[\r\n]/,'').split.join(" ")
   link = node.css('a')[0]

   record[:link] = link['id'] if !link.nil?

   array_of_records << record
  }

此代码设法捕获我正在解析的标题并将其内容存储在哈希中

 {heading: "content"} 

但没有捕获我需要捕获的类似父级的信息。

标签: htmlrubyparsingnokogiri

解决方案


traverse是个好主意。您想跟踪最新的 h1、h2、h3 等:...

@state = {}
records = []
nokogiri_object.traverse { |node|
  next unless desired_headings.include?(node.name)
  @state[node.name] = node.text
  case node.name
    when 'h1'
      records << {
        h1: @state['h1']
      }
    when 'h2'
      records << {
        h1: @state['h1'],
        h2: @state['h2'],
      }

  end
}

推荐阅读