Красивый суп: выделите строку в таблице, если ячейка содержит слово

#python #css #beautifulsoup

#python #css #beautifulsoup

Вопрос:

Спасибо, если вы обратили внимание на мой пост,

После многих исследований я не смог найти среднее значение для очистки строки таблицы только в том случае, если ячейка содержит определенное значение.

Более конкретно: я хочу сохранить строку, содержащую слово «oui», в последнем столбце следующей таблицы:

 <table align="center" cellspacing="0" cellpadding="3" width="100%">
<tbody><tr>
<td class="tdhg" align="left"><b>Liste des candidats</b></td>
<td class="tdhv"><strong>Voix</strong></td>
<td class="tdhv"><strong>%amp;nbsp;Inscrits</strong></td>
<td class="tdhv"><strong>%amp;nbsp;Exprimés</strong></td>
<td class="tdhv"><strong>Elu(e)</strong></td>
</tr>
<tr>
<td class="tdcbf" align="left">M.amp;nbsp;Jean-François LAMOURamp;nbsp;(UMP) </td>
<td class="tdcd" align="right">23amp;nbsp;964</td>
<td class="tdcd" align="right">  33,01</td>
<td class="tdcd" align="right">  54,60</td>
<td class="tdcd" align="center">oui
                          amp;nbsp;</td>
</tr>
<tr>
<td class="tdcbf" align="left">M.amp;nbsp;Gilles ALAYRACamp;nbsp;(RDG) </td>
<td class="tdcd" align="right">19amp;nbsp;927</td>
<td class="tdcd" align="right">  27,45</td>
<td class="tdcd" align="right">  45,40</td>
<td class="tdcd" align="center">
                          amp;nbsp;</td>
</tr>
</tbody></table> 

Сначала я попытался выполнить регулярное выражение, я успешно нашел подходящее слово, но сохранить соответствующую строку кажется сложным, поэтому я решил изменить метод и пройти BeautifulSoup.

Лучшее, что я сделал на данный момент, это:

 url='www.someurl.com'
headers = {"User-Agent":"Mozilla/5.0"}
response = requests.get(url.format())
html_soup = soup(response.content, 'lxml')
html_soup.select('td.tdcd')
 

Я не могу пойти дальше, в частности, заявив, что нужно сохранить ‘tr’ там, где ‘tdcd’ содержит ‘oui’. Даже если я прочитал документацию https://www.crummy.com/software/BeautifulSoup/bs4/doc /, довольно сложно рассматривать значение ячейки как дочерней, если я не ошибаюсь.

Спасибо,

Ответ №1:

найдите td.tdcd то, что содержит oui , выберите его родительским

 html_soup = soup(response.content, 'lxml')
tds = html_soup.select('td.tdcd')

for td in tds :
  if 'oui' in td.text:
    print(td.parent)
 

Комментарии:

1. Большое вам спасибо, это определенно то, что я искал! Я сосредоточился на детях, а не на родителях, это довольно интересный подход. И последний маленький вопрос: почему только td.parent отображает строку без «oui» внутри (это просто для полного понимания механики)?

2. это отображение oui , на котором вы можете его протестировать repl.it/@uingtea/PythonTester

Ответ №2:

Это то, что вам нужно? Просто считайте в фрейм данных, а затем фильтруйте фрейм данных

 html = '''<table align="center" cellspacing="0" cellpadding="3" width="100%">
<tbody><tr>
<td class="tdhg" align="left"><b>Liste des candidats</b></td>
<td class="tdhv"><strong>Voix</strong></td>
<td class="tdhv"><strong>%amp;nbsp;Inscrits</strong></td>
<td class="tdhv"><strong>%amp;nbsp;Exprimés</strong></td>
<td class="tdhv"><strong>Elu(e)</strong></td>
</tr>
<tr>
<td class="tdcbf" align="left">M.amp;nbsp;Jean-François LAMOURamp;nbsp;(UMP) </td>
<td class="tdcd" align="right">23amp;nbsp;964</td>
<td class="tdcd" align="right">  33,01</td>
<td class="tdcd" align="right">  54,60</td>
<td class="tdcd" align="center">oui
                          amp;nbsp;</td>
</tr>
<tr>
<td class="tdcbf" align="left">M.amp;nbsp;Gilles ALAYRACamp;nbsp;(RDG) </td>
<td class="tdcd" align="right">19amp;nbsp;927</td>
<td class="tdcd" align="right">  27,45</td>
<td class="tdcd" align="right">  45,40</td>
<td class="tdcd" align="center">
                          amp;nbsp;</td>
</tr>
</tbody></table>'''

import pandas as pd

table = pd.read_html(html)[0]

# Keep any rows that have 'oui' in the row; doesn't matter which column
filter_table = table[table.values == 'oui']

# Or if you specifically need to look in the last column
#filter_table = table[table.iloc[:,-1] == 'oui']

# Or specific column name
#filter_table = table[table[4] == 'oui']
 

Вывод:

 print (filter_table)
                               0       1     2     3    4
1  M. Jean-François LAMOUR (UMP)  23 964  3301  5460  oui
 

Альтернативный вариант:

Здесь вы можете перебирать строки и добавлять только в том случае, если они содержат 'oui'

 html_soup = BeautifulSoup(html, 'lxml')
data_rows = html_soup.select('tr')

rows = []
for row in data_rows:
    data = [ x.text.strip() for x in row.find_all('td',{'class':'tdcd'})]
    if 'oui' in data:
        rows.append(data)
        
table = pd.DataFrame(rows)
 

Комментарии:

1. Спасибо за этот ответ, который кажется вполне последовательным. Ну, я не думал о фильтрации на этапе panda, но это может помочь. Проблема в том, что я удаляю кучу переменных на одних и тех же страницах, чтобы они повторялись на каждой странице для каждой строки (даже если она не содержит ‘oui’) и потому, что у меня много страниц, которые я хотел отфильтровать перед сохранением в файл panda.

2. ах, хорошо. Я тоже буду работать над альтернативным решением. Но Я. Это имеет смысл

3. Большое вам спасибо!