【问题标题】:Wrapping html in new tag based on text beautifulsoup基于文本beautifulsoup将html包装在新标签中
【发布时间】:2018-05-03 20:34:37
【问题描述】:

我想在一个 html 块周围包裹一个新的<tr>,但是 html 没有任何唯一的标签,我可以用它来区分标签的开头和结尾。我是使用 BeautifulSoup 的新手,一般来说,当我操纵汤对象时,它会操纵整个标签。因此,我发现很难跨多个标签工作,这些标签除了文本之外没有唯一标识。 html看起来像

<td>
  <th>Id</th>
  <td>1234</td>
  <th>something</th>
  <td>some text</td>
  <th>Id</th>
  <td>2345</td>
  <th>anything</th>
  <td>other text</td>
</td>

我希望每次看到 &lt;th&gt;Id&lt;/th&gt; 时都将其包装在 &lt;tr&gt; 标记中,使其看起来像:

<td>
  <tr>
    <th>Id</th>
    <td>1234</td>
    <th>something</th>
    <td>some text</td>
  </tr>
  <tr>
    <th>Id</th>
    <td>2345</td>
    <th>anything</th>
    <td>other text</td>
  </tr>
</td>

我也一直在尝试正则表达式,但由于 Id 是唯一一致的表头,而所有其他表头也由 &lt;th&gt; 标签设置,所以我没有得到正确的组合。

【问题讨论】:

    标签: python html beautifulsoup


    【解决方案1】:

    步骤:

    • 遍历所有&lt;th&gt;&lt;td&gt; 标签。
    • 如果tag.text'Id',则使用wrap()new_tag() 用新的&lt;tr&gt; 标记包装该标记。
      • 使用.parent将新创建的&lt;tr&gt;标签保存在一个变量中
    • 否则,使用extract() 提取标签,然后使用append() 将其附加到先前创建的&lt;tr&gt; 标签的内容中。

    代码:

    html = '''
    <td>
      <th>Id</th>
      <td>1234</td>
      <th>something</th>
      <td>some text</td>
      <th>Id</th>
      <td>2345</td>
      <th>anything</th>
      <td>other text</td>
    </td>'''
    
    soup = BeautifulSoup(html, 'html.parser')
    
    curr_tag = ''
    for tag in soup.td.find_all(['td', 'th']):
        if tag.text == 'Id':
            tag.wrap(soup.new_tag('tr'))
            curr_tag = tag.parent
        else:
            curr_tag.append(tag.extract())
    
    print(soup)
    

    输出:

    <td>
      <tr>
        <th>Id</th>
        <td>1234</td>
        <th>something</th>
        <td>some text</td>
      </tr>
      <tr>
        <th>Id</th>
        <td>2345</td>
        <th>anything</th>
        <td>other text</td>
      </tr>
    </td>
    

    【讨论】:

      【解决方案2】:

      你可以使用itertools.groupby:

      import itertools, re
      s = """
      <td>
      <th>Id</th>
      <td>1234</td>
       <th>something</th>
       <td>some text</td>
       <th>Id</th>
       <td>2345</td>
       <th>anything</th>
      <td>other text</td>
      <td>
      """
      [_, top], *main = [[a, list(b)] for a, b in itertools.groupby(filter(None, s.split('\n')), key=lambda x:bool(re.findall('\<th\>Id\<', x)))]
      new_main = ['<tr>\n{}'.format('\n'.join(b)) if a else '{}\n</tr>'.format('\n'.join(b)) if i < len(main)-1 else '{}\n</tr>\n{}'.format('\n'.join(b[:-1]), b[-1]) for i, [a, b] in enumerate(main)]
      final_result = '{}\n{}'.format('\n'.join(top), '\n'.join(new_main))
      

      输出:

      <td>
       <tr>
       <th>Id</th>
       <td>1234</td>
       <th>something</th>
       <td>some text</td>
       </tr>
      <tr>
       <th>Id</th>
       <td>2345</td>
       <th>anything</th>
       <td>other text</td>
       </tr>
      <td>
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2023-03-08
        • 1970-01-01
        • 1970-01-01
        • 2010-10-26
        • 2014-05-03
        • 1970-01-01
        • 2019-07-26
        • 1970-01-01
        相关资源
        最近更新 更多