9

Rubyを使用してドキュメントからHTMLタグを削除する方法の例はたくさんあります。HpricotとNokogiriには、すべてのHTMLを簡単かつ迅速に削除するinner_textメソッドがあります。

私がやろうとしているのは逆で、HTMLドキュメントからすべてのテキストを削除し、タグとその属性だけを残します。

私はinner_htmlをnilに設定するドキュメントをループすることを検討しましたが、最初の要素(ルート)にはドキュメントの残り全体のinner_htmlがあるため、実際にはこれを逆に行う必要があります。理想的には、最も内側の要素であり、祖先を上に移動しながら、inner_htmlをnilに設定します。

これを効率的に行うためのちょっとしたコツを知っている人はいますか?私はおそらく正規表現がそれを行うかもしれないと思っていましたが、おそらくHTMLトークナイザー/パーサーほど効率的ではありません。

4

4 に答える 4

38

これも機能します:

doc = Nokogiri::HTML(your_html)
doc.xpath("//text()").remove
于 2009-09-30T14:29:14.060 に答える
3

文字列をスキャンして「トークン」の配列を作成し、htmlタグであるもののみを選択できます。

>> some_html
=> "<div>foo bar</div><p>I like <em>this</em> stuff <a href='http://foo.bar'> long time</a></p>"
>> some_html.scan(/<\/?[^>]+>|[\w\|`~!@#\$%^&*\(\)\-_\+=\[\]{}:;'",\.\/?]+|\s+/).select { |t| t =~ /<\/?[^>]+>/ }.join("")
=> "<div></div><p><em></em><a href='http://foo.bar'></a></p>"

==編集==

またはさらに良いことに、htmlタグをスキャンするだけです;)

>> some_html.scan(/<\/?[^>]+>/).join("")
=> "<div></div><p><em></em><a href='http://foo.bar'></a></p>"
于 2009-09-30T12:13:35.847 に答える
3

タグに含まれていないものをすべて取得するには、次のようにnokogiriを使用できます。

doc.search('//text()').text

もちろん、タグの内容<script><style>タグなどが取得されるため、ブラックリストに登録されたタグを削除することもできます。

blacklist = ['title', 'script', 'style']
nodelist = doc.search('//text()')
blacklist.each do |tag|
  nodelist -= doc.search('//' + tag + '/text()')
end
nodelist.text

必要に応じてホワイトリストに登録することもできますが、それはおそらくより時間がかかるでしょう。

whitelist = ['p', 'span', 'strong', 'i', 'b']  #The list goes on and on...
nodelist = Nokogiri::XML::NodeSet.new(doc)
whitelist.each do |tag|
  nodelist += doc.search('//' + tag + '/text()')
end
nodelist.text

また、巨大なXPath式を作成して、1回の検索を実行することもできます。正直なところ、どちらの方が速いのか、あるいはかなりの違いがあるのか​​どうかはわかりません。

于 2009-09-30T14:03:59.287 に答える
0

私はこれを思いついたばかりですが、@ andre-rのソリューションは非常に優れています!

#!/usr/bin/env ruby

require 'nokogiri'

def strip_text doc
  Nokogiri(doc).tap { |doc|
    doc.traverse do |node|
      node.content = nil if node.text?
    end
  }.to_s
end

require 'test/unit'
require 'yaml'
class TestHTMLStripping < Test::Unit::TestCase
  def test_that_all_text_gets_strippped_from_the_document
    dirty, clean = YAML.load DATA
    assert_equal clean, strip_text(dirty)
  end
end
__END__
---
- |
  <!DOCTYPE html>
  <html xmlns='http://www.w3.org/1999/xhtml' xml:lang='en' lang='en'>
    <head>
        <meta http-equiv='Content-type'     content='text/html; charset=UTF-8' />
        <title>Test HTML Document</title>
        <meta http-equiv='content-language' content='en' />
    </head>
    <body>
        <h1>Test <abbr title='Hypertext Markup Language'>HTML</abbr> Document</h1>
        <div class='main'>
            <p>
                <strong>Test</strong> <abbr title='Hypertext Markup Language'>HTML</abbr> <em>Document</em>
            </p>
        </div>
    </body>
  </html>
- |
  <!DOCTYPE html>
  <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
  <head>
  <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
  <title></title>
  <meta http-equiv="content-language" content="en">
  </head>
  <body><h1><abbr title="Hypertext Markup Language"></abbr></h1><div class="main"><p><strong></strong><abbr title="Hypertext Markup Language"></abbr><em></em></p></div></body>
  </html>
于 2009-09-30T14:55:52.363 に答える