删除Ruby中的特定HTML元素

时间:2012-11-10 05:01:23

标签: html ruby

我在Ruby中看到过基于白名单的HTML清理程序,但我需要相反的情况,我只需要从页面中删除链接以便为PDF转换做好准备。我尝试了Sanitize,但它不符合我的需要,因为很难猜测在获取的页面上将使用哪些HTML元素,因此我可以将它们添加到列表中。

如果我的输入是

<a href="link">Link!</a>
<b>Bold Text</b>
<div>A div!</div>

我想要

Link!
<b>Bold Text</b>
<div>A div!</div>

是输出。

是否有基于黑名单的消毒剂&#39;对于Ruby?

4 个答案:

答案 0 :(得分:2)

您想要一个HTML解析器,例如Nokogiri。它允许您遍历文档,搜索特定节点(“标签”)并对其执行操作:

require 'nokogiri'

html = '<a href="link">Link!</a>
<b>Bold Text</b>
<div>A div!</div>
'

doc = Nokogiri.HTML(html)

doc.search('a').each do |a|
  a.replace(a.content)
end

puts doc.to_html

结果是:

<html><body>Link!
<b>Bold Text</b>
<div>A div!</div>
</body></html>

请注意,Nokogiri对代码进行了一些修正,提供了相应的<html><body>标记。它没有,我可以告诉它使用并返回一个文档片段,但通常我们让它做它的事情。

答案 1 :(得分:1)

Tin Man的回答略有不同,仍在使用Nokogiri

require 'nokogiri' # gem install nokogiri
doc = Nokogiri.HTML( my_html )
doc.css('a,blink,marquee').each do |el|
  el.replace( el.inner_html )
end
cleaned = doc.to_html

这里的两个不同之处是:

  1. 使用css而非search稍微更具体地说明所使用的选择器(虽然它没有提供任何功能差异),但更重要的是

  2. 通过替换为inner_html,我们在链接中保留了可能的标记。例如,给定标记:

    <p><a href="foo">Hi <b>Mom</b></a>!</p>
    

    然后用.content替换会产生:

    <p>Hi Mom!</p>
    

    而用.inner_html替换会产生:

    <p>Hi <b>Mom</b>!</p>
    

答案 2 :(得分:1)

Rails 4.2可以开箱即用。对于旧版本,gem 'rails-html-sanitizer'是必需的

白名单仅提供标签和属性

white_list_sanitizer = Rails::Html::WhiteListSanitizer.new
white_list_sanitizer.sanitize(@article.body, tags: %w(table tr td), attributes: %w(id class style))

或使用Loofah的TargetScrubber

的Rails :: HTML :: TargetScrubber

当PermitScrubber选择标签和属性以允许进行清理时,Rails :: Html :: TargetScrubber将它们作为目标进行删除。

scrubber = Rails::Html::TargetScrubber.new
scrubber.tags = ['img']

html_fragment = Loofah.fragment('<a><img/ ></a>')
html_fragment.scrub!(scrubber)
html_fragment.to_s # => "<a></a>"

Rails HTML sanitizer

答案 3 :(得分:0)

html_without_links = remove_tags("<a href="link">Link!</a><b>Bold Text</b><div>A div!</div>",'a')

你可以使用上面的方法和下面的代码,你应该得到你想要的。

require 'nokogiri'

def is_html?(text)
  stripped_text = Nokogiri::HTML(text).text.strip
  return !stripped_text.eql?(text)
end

def remove_tags(message_string,tag=nil)
  return message_string if message_string.blank? || tag.blank? || !is_html?(message_string)
  html_doc = Nokogiri.HTML(message_string)
  html_doc.search(tag).each do |a|
    a.replace(a.content)
  end

  html_doc.text
end