【问题标题】:How to use Nokogiri to replace "inner_html" of text string如何使用 Nokogiri 替换文本字符串的“inner_html”
【发布时间】:2020-10-01 14:01:22
【问题描述】:

我想获取一个 HTML 字符串并返回一个保留 HTML 结构但带有混淆文本/内部 HTML 的变异版本。

例如:

string = "<div><p><h1>this is some sensitive text</h1><br></p><p>more text</p></div>"
obfuscate_html_string(string)
=> "<div><p><h1>**** **** **** **** ****</h1><br></p><p>**** ****</p></div>"

我进行了实验,虽然 inner_html= 方法似乎很有用,但它引发了一个参数错误:

Nokogiri::HTML.fragment(value).traverse { |node| node.content = '***' if node.inner_html }.to_s
=> "***"

Nokogiri::HTML.fragment(value).traverse { |node| node.content ? node.content = '***' : node.to_html }.to_s
=> "***"

Nokogiri::HTML.fragment(value).traverse { |node| node.inner_html = '***' if node.inner_html }.to_s
=> ArgumentError: cannot reparent Nokogiri::XML::Text there

【问题讨论】:

标签: html ruby nokogiri obfuscation


【解决方案1】:

这应该会有所帮助,但文档会更详细地介绍这一点。

您的 HTML 有问题,因为它是无效的,这迫使 Nokogiri 进行修复,届时将更改 HTML:

require 'nokogiri'

doc = Nokogiri::HTML("<div><p><h1>this is some sensitive text</h1><br></p><p>more text</p></div>")
doc.errors # => [#<Nokogiri::XML::SyntaxError: 1:53: ERROR: Unexpected end tag : p>]
doc.to_html
# => "<!DOCTYPE html PUBLIC \"-//W3C//DTD HTML 4.0 Transitional//EN\" \"http://www.w3.org/TR/REC-html40/loose.dtd\">\n" +
#    "<html><body><div>\n" +
#    "<p></p>\n" +
#    "<h1>this is some sensitive text</h1>\n" +
#    "<br><p>more text</p>\n" +
#    "</div></body></html>\n"

Nokogiri 报告 HTML 中存在错误,因为您不能在 p 中嵌套 h1 标记:

ERROR: Unexpected end tag : p>

这意味着它无法理解 HTML,并尽最大努力通过提供/更改结束标记来恢复,直到它理解为止。这并不意味着 HTML 实际上是您或作者想要的。

从那时起,您查找节点的尝试可能会失败,因为 DOM 已更改。

总是检查errors,如果它不是空的,要非常小心。最好的解决方案是通过 Tidy 或类似的方式运行该 HTML,然后处理其输出。

不过,从那时起,这应该可行:

node = doc.at('div h1')
node.inner_html = node.inner_html.tr('a-z', '*')

node = doc.search('div p')[1]
node.inner_html = node.inner_html.tr('a-z', '*')

puts doc.to_html

# >> <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN" "http://www.w3.org/TR/REC-html40/loose.dtd">
# >> <html><body><div>
# >> <p></p>
# >> <h1>**** ** **** ********* ****</h1>
# >> <br><p>**** ****</p>
# >> </div></body></html>

【讨论】:

  • 谢谢,虽然不是我想要的。理想情况下,我需要迭代每个节点并替换 html 的东西,而不需要引用特定的标签。
  • 这种方法的问题是你最终会写出非常低效的代码;逐个节点遍历文档很慢,并且存在大量冗余检查。您知道只有某些类型的标签可以包含您想要的文本类型,因此针对这些类型,或者至少只搜索文本节点。 HTML 文档往往是重复的,因为只允许某些节点包含文本,因此查找这些文本很容易。
猜你喜欢
  • 1970-01-01
  • 2015-11-04
  • 1970-01-01
  • 2021-02-08
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多