1

Nokogiri および CSS セレクターを使用してウィキペディアの記事を解析するスクリプトを Ruby で作成しようとしています。ただし、スクリプト内の条件について少し混乱しています。これが私がこれまでに持っているものです(pageNokogiriを使用してダウンロードしたhtmlです):

page.css('h3').each do |node|
  puts node.text
end

page.css('li').each do |node|   
  if /\d|\D/.match(node)
    puts node.text.scan(/[\d]+\D*/).first
  end
end

page.css('td b').each do |node|
  puts node.text
end

これはすべてうまくいきます。しかし、私が本当に欲しいのは次のようなものです:

page.css('h3, li, td b').each do |node|
  # if it's an h3 node, do one thing
  # if it's a li node, do another thing
  # else if it's a 'td b' node, do another thing
end

これにより、本文を 3 回別々に処理する代わりに、ページを順番に解析できます。ただし、スクリプト内でこれらの条件を記述する方法がわかりません。

編集:だから今私のスクリプトは

page.css('h3, li, td b').each do |node|
        case node.name
        when 'h3', 'b'
            puts node.text
        when 'li'
            if /\d|\D/.match(node)
                puts node.text.scan(/[\d]+\D*/).first
            end
        else
            next
    end
end

ただし、動作は変更されていません。以前と同じ順序でそれらを処理します (すべての 'h3' 要素、次にすべての 'li' 要素、次にすべての 'b' 要素)。

編集2:

さて、私はついにそれを働かせました。これが私の最終的な条件セットです。

page.traverse do |node|
    case
            when 'h3' == node.name 
            puts node.text
        when 'li' == node.name 
            puts node.text.scan(/[\d]+\D*/).first if /\d|\D/.match(node)
        when 'b' == node.name
            puts node.text if (node.parent.name == 'p' or node.parent.name == 'td')
    end
end

ありがとう!

4

2 に答える 2

3

あなたはトラバースを探しているかもしれません:

page.traverse do |node|
  case
    when ['h3', 'li'].include?(node.name) then puts node.text
    when 'b' == node.name && 'td' == node.parent.name then puts node.text[/\d+\D*/]
  end
end
于 2012-05-19T01:54:48.770 に答える
3

Nokogiri を使用すると、最初のシナリオであっても、ページが 3 回に分けて解析されることはありません。Nokogiri はページを 1 回解析し、インメモリ DOM を作成してから、その DOM を使用して目的のノードを検索します。複数の CSS または XPath ルックアップを実行することは非効率的ではありません。

それにもかかわらず、一度にすべてのノードを取得したい場合は、次のようにすることができます。

page.css('h3, li, td b').each do |node|
  case node.name
  when 'h3'
    do_something
  when 'li'
    do_something_else
  when 'b'
    do_another_thing
end

td baとa などを区別する必要がある場合p b、この手法は機能しないことに注意してください。別々のルックアップをお勧めします。

于 2012-05-19T00:26:56.167 に答える