提取部分代码并在bash中解析HTML

时间:2016-12-06 17:36:15

标签: bash html-parsing

我有外部HTML网站,我需要从该网站上的表中提取数据。但是,除了代码中的表格之外,HTML网站的源代码格式错误,因此我无法使用

xmllint --html --xpath <xpath> <file>

因为当网站上的HTML格式被破坏时它无法正常工作。

我的想法是使用curl并删除表格上方和下方的代码。提取表时,代码是干净的,它适合 xmllint 工具(我可以使用xpath)。但是,删除匹配项上方的所有内容对于shell都具有挑战性,您可以在此处看到:Sed doesn't backtrack: once it's processed a line, it's done. 有没有办法如何从bash中的HTML网站中仅提取表的代码? Suposse,代码有这种结构。

<html>
<head>
</head>
<body>
<p>Lorem ipsum ....</p>
  <table class="my-table">
    <tr>
      <th>Company</th>
      <th>Contact</th>
    </tr>
  </table>
<p>... dolor.</p>
</body>
</html>

我需要这样的输出来正确解析数据:

  <table class="my-table">
    <tr>
      <th>Company</th>
      <th>Contact</th>
    </tr>
  </table>

请不要因为尝试使用bash而给我减去。

2 个答案:

答案 0 :(得分:8)

我将分解我尝试使用xmllint尝试的答案,{{3}}支持--html标记来解析html个文件

首先,您可以通过解析下面的HTML文件来检查HTML文件的完整性,该文件确认文件是否符合标准,或者如果出现错误则抛出错误: -

$ xmllint --html YourHTML.html
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN" "http://www.w3.org/TR/REC-html40/loose.dtd">
<html>
<head>
</head>
<body>
<p>Lorem ipsum ....</p>
  <table class="my-table">
    <tr>
      <th>Company</th>
      <th>Contact</th>
    </tr>
  </table>
<p>... dolor.</p>
</body>
</html>

我的原始YourHTML.html文件只是您问题中的输入HTML文件。

现在为值提​​取部分: -

启动文件从根节点解析到table节点(//html/body/table)并在HTML解析器&amp;中运行xmllint交互式shell模式(xmllint --html --shell

明确地运行命令会产生一个结果,

$ echo "cat //html/body/table" |  xmllint --html --shell YourHTML.html
/ >  -------
<table class="my-table">
    <tr>
      <th>Company</th>
      <th>Contact</th>
    </tr>
  </table>
/ > 

现在使用sed删除特殊字符,即sed '/^\/ >/d'生成

$ echo "cat //html/body/table" |  xmllint --html --shell YourHTML.html | sed '/^\/ >/d'
<table class="my-table">
    <tr>
      <th>Company</th>
      <th>Contact</th>
    </tr>
  </table>

这是您期望的输出结构。在xmllint: using libxml version 20900

上测试过

我将再向前迈一步,如果你想获取table标签中的值,你可以应用sed命令将它们提取为

$ echo "cat //html/body/table" |  xmllint --html --shell YourHTML.html | sed '/^\/ >/d' | sed 's/<[^>]*.//g' | xargs
Company Contact

答案 1 :(得分:1)

我不确定为什么没有人提及纯Bash解决方案,尽管有其局限性(例如,同一行上没有html标记结尾的文件-不过您说您已经清理了.html)

出于您的目的,一种快速的解决方案是使用1-liner:

sed -n '/<table class="my-table">/,/<\/table>/p'  <file>

说明: 打印两个指定标签之间的所有内容,在这种情况下为<table>

您还可以轻松地为<body><p>设置标签变量,并即时更改输出。但是上述解决方案可以提供您不需要外部工具的要求。