使用Nokogiri / Rspec同时解析许多文件

时间:2013-09-07 03:31:32

标签: ruby rspec nokogiri

我有一个主解析方法,由解析html文件的其他方法组成:

class Parser
  def self.parse(html)
    @data = Nokogiri.HTML(open(html))
    merged_hashes = {}

    array_of_hashes = [
      parse_title,
      parse_description,
      parse_related
    ]
    array_of_hashes.inject(merged_hashes,:update)

    return merged_hashes
  end

  def self.parse_title
    title_hash = {}

    title = @data.at_css('.featureProductInfo a')
    return title_hash if title.nil?
    title_hash[:title] = @data.at_css('.featureProductInfo a').text

    title_hash
  end
  .
  .
  .

所以我在Rspec中这样做:

require File.dirname(__FILE__) + '/parser.rb'

def html_starcraft
  File.open("amazon_starcraft.html")
end

describe ".parse_title (StarCraft)" do
  let(:title_hash) { Parser.parse html_starcraft } 

  it "scraps the featured product title" do
    expect(title_hash[:title]).to eq("StarCraft II: Wings of Liberty (Bradygames Signature Guides)")
  end
end

正如您所看到的,我一次只解析一个文件。我怎样才能同时解析许多?比如,解析文件夹中的所有文件?

1 个答案:

答案 0 :(得分:2)

正如@theTinMan指出的那样,Nokogiri只会处理一个文件。如果要解析文件夹中的所有文件,则必须阅读该文件夹(再次,如@theTinMan指出的那样)和spawn a processthread

当然,您首先需要了解how fork workswhat is a thread

使用流程的示例

好的,让我们使用一个进程,因为ruby没有真正的线程:

files = Dir.glob("files/**")

files.each do |file|
  # Here the program become two: 
  # One executes the block, other continues the loop
  fork do 
    puts File.open(file).read
  end
end

# We need to wait for all processes to get to this point
# Before continue, because if the main program dies before
# its children, they are killed immediately. 
Process.waitall
puts "All done. closing."

和输出:

$ ls files/
a.txt  b.txt  c.txt  d.txt
$ ruby script.rb 
Content of a.txt
Content of b.txt
Content of d.txt
Content of c.txt
All done. closing.

请注意,由于它是并发的,因此每次执行程序时,读取文件的顺序都会改变。