【问题标题】:Extract HTML comments in Python, using regex or lxml?使用 regex 或 lxml 在 Python 中提取 HTML 注释?
【发布时间】:2016-07-27 14:57:48
【问题描述】:

如何使用 Python 从文档中提取所有 HTML 样式的 cmets?

我尝试过使用正则表达式:

text = 'hello, world <!-- comment -->'
re.match('<!--(.*?)-->', text)

但它什么也没产生。我不明白这一点,因为相同的正则表达式在 https://regex101.com/ 的同一字符串上运行良好

更新:我的文档实际上是一个XML文件,我正在用pyquery(基于lxml)解析文档,但我不认为lxml可以extract comments that aren't inside a node。这是文档的样子:

<?xml version="1.0" encoding="UTF-8"?>
<clinical_study rank="220398">
  <intervention_browse>
    <!-- CAUTION:  The following MeSH terms are assigned with an imperfect algorithm  -->
    <mesh_term>Freund's Adjuvant</mesh_term>
    <mesh_term>Keyhole-limpet hemocyanin</mesh_term>
  </intervention_browse>
  <!-- Results have not yet been posted for this study                                -->
</clinical_study>

更新 2:感谢您提出其他答案,但我已经使用 lxml 广泛解析文档,并且不想用 BeautifulSoup 重写所有内容。已相应更新标题。

【问题讨论】:

  • 使用 lxml 或 beautifulsoup 会更简单且更可靠
  • @MaxU 我已经在使用 lxml (pyquery),所以我真的不想切换到 BeautifulSoup,但谢谢。我已经更新了问题,明确表示我很乐意使用正则表达式或 lxml。
  • @Padraic 我不确定在 lxml 中是否真的可行,请参阅更新。
  • @Richard dox 您链接到建议您可以确定tag 是否是etree.comment - 你试过吗?然后如果True 可以打印tag 属性值?
  • @DavidZemens 的问题是没有tag,评论只是浮动的。

标签: python regex


【解决方案1】:

这似乎是为我打印评论:

from lxml import etree
txt = """<?xml version="1.0" encoding="UTF-8"?>
<clinical_study rank="220398">
  <intervention_browse>
    <!-- CAUTION:  The following MeSH terms are assigned with an imperfect algorithm  -->
    <mesh_term>Freund's Adjuvant</mesh_term>
    <mesh_term>Keyhole-limpet hemocyanin</mesh_term>
  </intervention_browse>
  <!-- Results have not yet been posted for this study                                -->
</clinical_study>"""
root = etree.XML(txt)
print root[0][0]

要获得最后条评论:

comments = [itm for itm in root if itm.tag is etree.Comment]:
if comments:
    print comments[-1]

【讨论】:

  • 谢谢!这实际上是我关心的最后一条评论(在具有任意数量 cmets 的文档中,尽管最后一条评论总是在结束 clinical_study 标记之前)知道你是如何得到它的吗?
  • root[0] 似乎做到了。谢谢!
  • root[1] 为我打印&lt;!-- Results have not yet been posted for this study --&gt;
  • 干杯,如果它有效@Richard 请考虑将此答案标记为“已接受”。
【解决方案2】:

你必须使用 re.findall() 方法来提取所有匹配特定模式的子字符串。

re.match() 只会检查模式是否适合字符串的开头,而 re.search() 只会让您找到字符串中的第一个匹配项。出于您的目的, re.findall() 绝对是正确的方法,应该首选。

【讨论】:

    【解决方案3】:

    XPath 在这里工作得很好:tree.xpath('//comment()')。例如,您可以从 DOM 中删除所有脚本、样式和 cmets:

    tree = lxml.html.fromstring(html)
    for el in tree.xpath('//script | //style | //comment()'):
        el.getparent.remove(el)
    

    没有美丽的汤。

    【讨论】:

      【解决方案4】:

      您可以使用 Beautiful Soup's 在这样的 for 循环中提取注释

      from bs4 import BeautifulSoup, Comment
      
      text = 'hello, world <!-- comment -->'
      
      soup = BeautifulSoup(text, 'lxml')
      
      for x in soup.findAll(text=lambda text:isinstance(text, Comment)):
          print(x)
      

      【讨论】:

        【解决方案5】:

        match 更改为search 然后:

        text = 'hello, world <!-- comment -->'
        comment = re.search('<!--(.*?)-->', text)
        comment.group(1)
        

        输出:

        ' comment '
        

        【讨论】:

          猜你喜欢
          • 2015-03-28
          • 1970-01-01
          • 1970-01-01
          • 2015-08-24
          • 2015-10-06
          • 2016-05-11
          • 2022-01-07
          • 1970-01-01
          • 2019-03-02
          相关资源
          最近更新 更多