如何使用 Nokogiri 正确修复未闭合的 HTML 标签

Lui*_*lho 3 ruby nokogiri

我很难获取网站生成的 HTML。HTML 包含一些未封闭的标签。

例如:

<div>
  <li>
    <div>
      <div>
        test
      </div>

  <li>
     <div>
       test 
     </div>
Run Code Online (Sandbox Code Playgroud)

解析 HTML:

html = Nokogiri::HTML(open('origin.html'))
Run Code Online (Sandbox Code Playgroud)

结果是:

砍切物体

或者,在 HTML 中:

  <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN" "http://www.w3.org/TR/REC-html40/loose.dtd">

    <html><body>
      <div>

        <li>
          <div>
            <div>
              test
            </div>

        <li>
          <div>
            test 
          </div>

    </li>
    </div>
    </li>
    </div>
    </body>
    </html>
Run Code Online (Sandbox Code Playgroud)

我相信正确的事情应该是这样的:

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

      <li>
        <div>
           test 
        </div>
      </li>
    </div>
  </body>
</html>
Run Code Online (Sandbox Code Playgroud)

知道如何解决这个问题吗?换别的宝石?在解析之前使用正则表达式更改 HTML?

mat*_*att 6

您可以查看使用Nokogumbo ,它将Googles\xe2\x80\x99 Gumbo HTML5 解析器附加到 Nokogiri。然后,这将在解析格式错误的 HTML 时使用 HTML5 纠错算法,而不是执行我的 Nokogiri 和 libxml 的默认解析,并且将导致解析的 HTML 更接近您期望从浏览器看到的内容。

\n\n

Here\xe2\x80\x99s 是一个示例irb会话,显示它如何处理示例 HTML 并生成您想要的结果。请注意,方法名称为HTML5,并且仍然在模块上调用Nokogiri

\n\n
>> require \'nokogumbo\'\n=> true\n>> s = <<EOT\n<div>\n  <li>\n    <div>\n      <div>\n        test\n      </div>\n\n  <li>\n     <div>\n       test\n     </div>\nEOT\n=> "<div>\\n  <li>\\n    <div>\\n      <div>\\n        test\\n      </div>\\n\\n  <li>\\n     <div>\\n       test \\n     </div>\\n"\n>> puts Nokogiri.HTML5(s).to_html\n<html>\n<head></head>\n<body><div>\n  <li>\n    <div>\n      <div>\n        test\n      </div>\n\n  </div>\n</li>\n<li>\n     <div>\n       test\n     </div>\n</li>\n</div></body>\n</html>\n=> nil\n
Run Code Online (Sandbox Code Playgroud)\n