【问题标题】:How to split the tags from html tree如何从html树中拆分标签
【发布时间】:2012-02-05 23:34:56
【问题描述】:

这是我的 html 树

 <li class="taf"><h3><a href="26eOfferCode%3DGSONESTP-----------" id="pa1">
    Citibank <b>Credit Card</b> - Save over 5% on fuel | Citibank.co.in</a>
   </h3>Get the IndianOil Citibank <b>Card</b>. Apply Now! 
   <br />
   <a href="e%253DGOOGLE ------">Get 10X Rewards On Shopping</a> -
   <a href="S%2526eOfferCode%253DGSCCSLEX ------">Save Over 5% On Fuel</a>
   <br />
   <cite>www.citibank.co.in/<b>CreditCards</b></cite>
</li>

我需要从这个 html 中提取
标签之前的行

line1:获取 IndianOil Citibank 卡。现在申请!

line2 : 获得 10 倍的购物奖励 - 节省超过 5% 的燃料

在 python 中应该怎么做?

【问题讨论】:

  • 如果这不是唯一的情况并且您需要做更多这样的事情,请查看一些 (x)html 解析库。例如Beautiful Souplxml。在标准库中,有minidom,但我不喜欢它,而且它可能无法处理错误的语法(在现实世界中你会发现很多)。

标签: python beautifulsoup lxml


【解决方案1】:

不中继&lt;br&gt;标签的解决方案:

import lxml.html

html = "..."
tree = lxml.html.fromstring(html)
line1 = ''.join(tree.xpath('//li[@class="taf"]/text() | b/text()')[:3]).strip()
line2 = ' - '.join(tree.xpath('//li[@class="taf"]//a[not(@id)]/text()'))

【讨论】:

    【解决方案2】:

    不知道你是想用lxml还是美汤。但是对于使用 xpath 的 lxml,这里是一个示例

    import lxml
    from lxml import etree
    import urllib2
    
    response = urllib2.urlopen('your url here')
    html = response.read()
    imdb = etree.HTML(html)
    titles = imdb.xpath('/html/body/li/a/text()')//xpath for "line 2" data.[use firebug]
    

    我使用的xpath 用于您给定的html sn-p。它可能会在原始上下文中发生变化。

    你也可以试试cssselect in lxml

    import lxml.html
    import urllib
    data = urllib.urlopen('your url').read() 
    doc = lxml.html.fromstring(data)
    elements = doc.cssselect('your csspath here') // CSSpath[using firebug extension]
    for element in elements:
          print element.text_content() 
    

    【讨论】:

      【解决方案3】:

      与所有 HTML 解析一样,您需要对 HTML 的格式做出一些假设。如果我们可以假设前一行是&lt;br&gt; 标记之前的所有内容,直到块级标记,或者另一个&lt;br&gt;,那么我们可以执行以下操作...

      from BeautifulSoup import BeautifulSoup
      
      doc = """
         <li class="taf"><h3><a href="26eOfferCode%3DGSONESTP-----------" id="pa1">
          Citibank <b>Credit Card</b> - Save over 5% on fuel | Citibank.co.in</a>
          </h3>Get the IndianOil Citibank <b>Card</b>. Apply Now!
          <br />
          <a href="e%253DGOOGLE ------">Get 10X Rewards On Shopping</a> -
          <a href="S%2526eOfferCode%253DGSCCSLEX ------">Save Over 5% On Fuel</a>
          <br />
          <cite>www.citibank.co.in/<b>CreditCards</b></cite>
      </li>
      """
      
      soup = BeautifulSoup(doc)
      

      现在我们已经解析了 HTML,接下来我们定义我们不想作为行的一部分处理的标签列表。确实还有其他块标签,但这适用于这个 HTML。

      block_tags = ["div", "p", "h1", "h2", "h3", "h4", "h5", "h6", "br"]
      

      我们循环遍历每个&lt;br&gt; 标记,然后逐步返回其兄弟,直到我们没有更多标记,或者我们遇到块级标记。每次循环时,我们都会将节点添加到行的前面。 NavigableStrings 没有 name 属性,但我们希望包含它们,因此在 while 循环中进行了两部分测试。

      for node in soup.findAll("br"):
          line = ""
          sibling = node.previousSibling
          while sibling is not None and (not hasattr(sibling, "name") or sibling.name not in block_tags):
              line = unicode(sibling) + line
              sibling = sibling.previousSibling
          print line
      

      【讨论】:

        【解决方案4】:

        我想你只是在每个 &lt;br/&gt; 之前要求了一行。

        以下代码将为您提供的示例执行此操作,方法是去除&lt;b&gt;&lt;a&gt; 标记并打印following-sibling&lt;br/&gt; 的每个元素的.tail

        from lxml import etree
        
        doc = etree.HTML("""
        <li class="taf"><h3><a href="26eOfferCode%3DGSONESTP-----------" id="pa1">
            Citibank <b>Credit Card</b> - Save over 5% on fuel | Citibank.co.in</a>
           </h3>Get the IndianOil Citibank <b>Card</b>. Apply Now! 
           <br />
           <a href="e%253DGOOGLE ------">Get 10X Rewards On Shopping</a> -
           <a href="S%2526eOfferCode%253DGSCCSLEX ------">Save Over 5% On Fuel</a>
           <br />
           <cite>www.citibank.co.in/<b>CreditCards</b></cite>
        </li>""")
        
        etree.strip_tags(doc,'a','b')
        
        for element in doc.xpath('//*[following-sibling::*[name()="br"]]'):
          print repr(element.tail.strip())
        

        产量:

        'Get the IndianOil Citibank Card. Apply Now!'
        'Get 10X Rewards On Shopping -\n   Save Over 5% On Fuel'
        

        【讨论】:

        • doc.xpath('//*[following-sibling::br]') 也可以工作(没有name()="br")。
        • 我同意这个表达。我主要是为了上面的表达:"" 获得 IndianOil Citibank 卡。现在申请!无 - 无""
        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2015-02-14
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2021-06-04
        • 1970-01-01
        相关资源
        最近更新 更多