2

私は現在、Ruby と xPath を使用した小さな Web スクレイピング プロジェクトに取り組んでいます。残念ながら、ウェブサイトの構造が非常に悪いため、ちょっとした問題が発生します。

<h3>Relevant Headline</h3>
<p class="class_a class_b">Content starts in this paragraph...</p>
<p class="class_a ">...but this content belongs to the preceding paragraph</p>
<p class="class_a class_b">Content starts in this paragraph...</p>
<p class="class_a ">...but this content belongs to the preceding paragraph</p>
<h3>Some other Headline</h3>

ご覧のとおり、いくつかの p タグをフレーム化する 2 つの h3 タグがあります。フレーム化されたすべての p-tag を選択したい。私はすでにそれを行うために次のxPathを見つけました:

h3[contains(text(),"Relevant")]/following-sibling::p[1 = count(preceding-sibling::h3[1] | ../h3[contains(text(),"Relevant")])]

しかし、ここで問題が発生します。上記の 2 つの段落は一緒に属しています。class_b の段落 (最初の段落) は新しいデータ エントリを開始し、次の段落 (2 番目) はこのエントリに属します。3と4も同じです。問題は次のとおりです。3 つの段落が一緒に属する場合もあれば、4 つの段落が一緒に属する場合もありますが、ほとんどの場合、2 つの段落が一緒に属する場合があります。

これらの内側の段落をグループごとに選択し、Ruby で 1 つの文字列に結合するにはどうすればよいですか?

4

2 に答える 2

4

xpath と nokogiri を組み合わせて使用​​してもかまわない場合は、次のようにします。

paragraph_text = Array.new
doc.xpath('//p[preceding-sibling::h3[1][contains(text(), "Relevant")]]').each do |p|
    if p.attribute('class').text.include?('class_b')
        paragraph_text << p.content
    else
        paragraph_text[-1] += p.text
    end
end
puts paragraph_text
#=> ["Content starts in this paragraph......but this content belongs to the preceding paragraph",  "Content starts in this paragraph......but this content belongs to the preceding paragraph"]

基本的に、段落タグを取得するために xpath が使用されます。次に、nokogiri/ruby を使用して、段落を繰り返し処理し、文字列を作成します。

于 2012-11-14T22:29:00.877 に答える
3

xpath で実行できますが、slice_before でグループ化する方が簡単だと思います。

doc.search('*').slice_before{|n| n.name == 'h3'}.each do |h3_group|
  h3_group.slice_before{|n| n[:class] && n[:class]['class_b']}.to_a[1..-1].each do |p_group|
    puts p_group.map(&:text) * ' '
  end
end

アップデート

css を使用した別のオプション:

doc.search('p.class_b').each do |p|
  str, next_node = p.text, p
  while next_node = next_node.at('+ p:not([class*=class_b])')
    str += " #{next_node.text}"
  end
  puts str
end
于 2012-11-15T02:06:48.497 に答える