【问题标题】:Parse html with xmllint使用 xmllint 解析 html
【发布时间】:2021-07-12 05:54:54
【问题描述】:

我有一个这样的 HTML 代码

<dl>
 <dt><a href="element1" id="element1">element1</a> Version 1 </dt>
 <dd>Description 1</dd>
 <dt><a href="element2" id="element2">element2</a> Version 2 </dt>
 <dd>Description 2</dd>
...
</dl>

我想打印一个类似的输出

Item: element1, Version: Version1, Description: Description 1
Item: element2, Version: Version2, Description: Description 2
...

我尝试了几种方法,但我最好的方法是:

xmllint --xpath "concat('Item: ', //dl/dt/a/text(),', Version: ',', Description: ',//dl/dd/text())" file

#output
Item: element1, Version: , Description: Description 1

问题:

  • 无法获取版本
  • 无法获取所有元素

【问题讨论】:

  • 我不认为你可以用 xmllint 做到这一点;你可能需要一些支持 xquery 的东西,比如 xidel。
  • 您可以访问 xmlstarlet 吗?
  • xsltproc 在 html 模式下使用适当的样式表是更好的选择。

标签: bash html-parsing xmllint


【解决方案1】:

你可以使用html。以您为例:

text="""<dl>
 <dt><a href="element1" id="element1">element1</a> Version 1 </dt>
 <dd>Description 1</dd>
 <dt><a href="element2" id="element2">element2</a> Version 2 </dt>
 <dd>Description 2</dd>
...
</dl>"""

import htql
results = htql.query(text, "<dl>.<dt sep>2-0 {Item=<a>:tx; Version=<a>:xx; Description=<dd>:tx }")

然后显示结果:

>>> results
[('element1', ' Version 1 ', 'Description 1'), ('element2', ' Version 2 ', 'Description 2')]

【讨论】:

    【解决方案2】:

    如果您不必坚持使用 xmllint,这里有一种完成工作的纯 bash 方法:

    cat file | tr '>' '\n' | grep '.\+</' | cut -d '<' -f 1 | awk '{ if (NR%3==1) print "Item: "$0","; if (NR%3==2) print "Version: "$0","; if (NR%3==0) print "Description: "$0;}' | paste -sd '  \n' -
    

    解释:

    管道的第一部分:提取感兴趣的数据

    cat file | tr '>' '\n' | grep '.\+</' | cut -d '<' -f 1
    

    这个输出:

    element1
    Version 1
    Description 1
    element2
    Version 2
    Description 2
    

    管道的第二部分:基于行号的前缀名称

    awk '{ if (NR%3==1) print "Item: "$0","; if (NR%3==2) print "Version: "$0","; if (NR%3==0) print "Description: "$0;}'
    

    这个输出:

    Item: element1,
    Version:  Version 1 ,
    Description: Description 1
    Item: element2,
    Version:  Version 2 ,
    Description: Description 2
    

    管道的最后部分:每 3 行缝合一次

    paste -sd '  \n' -
    

    这会输出你想要的最终结果。

    【解决方案3】:

    根据@seagulf 的建议,使用 python 会更容易,

    results = htql.query(mystr, "<dl>.<dt sep>2-0 {Item=<a>:tx; Version=<a>:xx; Description=<dd>:tx } \n")
    for x in results:
        f.write ('{"item": "'+ x[0] + '", "version" : "' + x[1] + '", "description" : "' + x[2] + '"},\n')
    
    #output
    {"item": "element 1", "version" : "version 1", "description" : "description 1"},
    {"item": "element 2", "version" : "version 2", "description" : "description 2"},
    ...
    
    

    非常感谢!

    【讨论】:

      猜你喜欢
      • 2017-07-29
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-10-11
      • 2011-11-15
      • 2011-04-03
      • 2012-07-27
      相关资源
      最近更新 更多