Упаковка HTML в новый тег на основе текста beautifulsoup - PullRequest
0 голосов
/ 03 мая 2018

Я хотел бы обернуть новый <tr> вокруг блока html, но в 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>

Мне бы хотелось обернуть каждый раз, когда я вижу <th>Id</th> в теге <tr>, такой, что он выглядит так:

<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 - единственный непротиворечивый заголовок таблицы, в то время как все остальные заголовки также выделяются тегами <th>, я не получил правильную комбинацию.

Ответы [ 2 ]

0 голосов
/ 04 мая 2018

Шаги:

  • Перебирать все теги <th> и <td>.
  • Если tag.text равно 'Id', оберните этот тег новым тегом <tr>, используя wrap() и new_tag().
    • Сохраните вновь созданный тег <tr> в переменной, используя .parent
  • Иначе, извлеките тег, используя extract(), а затем добавьте его к ранее созданному содержимому тега <tr>, используя append().

Код:

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>
0 голосов
/ 03 мая 2018

Вы можете использовать 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>
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...