3 votes

Python : Comment obtenir une ligne de tableau par une chaîne de caractères à l'intérieur via BeatifullSoup ?

<tr class="list even">
    <td class="list">5</td>
    <td class="list"><s>BI</s>MU</td>
    <td class="list"><s>TEACHER</s>TEACHER</td>
    <td class="list">Hello I am a Text</td>
    <td class="list">5b</td>
    <td class="list">BI3</td></tr>

C'est l'une des lignes du tableau. Il y en a d'autres avec une ligne comme en-tête en ligne, mais je ne les connais pas.

Ainsi, je veux obtenir uniquement les lignes qui contiennent la chaîne "8f" mais pas seulement les td , l'ensemble tr Dans le cas où il y a plusieurs lignes contenant la chaîne de caractères, cela devrait me donner une liste de celles-ci.

for row in soup.find_all('tr', class_='list even'):
    if '5b' in row.text:
        print(row)
        for cell in row.find_all('td'):
            if "5b" not in cell.text:
                print(cell.text)

for row in soup.find_all('tr', class_='list odd'):
    if '5b' in row.text:
        for cell in row.find_all('td'):
            if "5b" not in cell.text:
                print(cell.text)

Je l'ai maintenant, mais il ajoute une nouvelle ligne avant le dernier champ de la table : https://haste.thevillage.chat/foguvakixa.py

if "5b" not in cell.text:

En effet, si je demande les données pour 5d, je n'ai pas besoin de savoir à nouveau qu'il s'agit de 5d. Donc cela filtre juste la classe elle-même

2voto

QHarr Points 24420

Vous pouvez utiliser pandas read_html pour récupérer la table puis filtrer sur la colonne klasse.

import pandas as pd

def get_lectures_two(df, klasse):    
    new_df = df[df['(Klasse(n))'] == klasse]
    return new_df

def get_df(url):
    df = pd.read_html(url)[0]
    df = df[~df['Stunde'].str.contains("LEHRER")]
    return df

df = get_df('https://niwla23.gitlab.io/download/vertreterdemo.html')
print(get_lectures_two(df, '5b'))

Avec bs4 4.7.1 +, vous pouvez utiliser :contains et :has, ainsi que l'index de colonne approprié via nth-of-type pour cibler les lignes appropriées (j'utilise pandas ici juste pour générer rapidement une belle sortie tabulaire pour la visualisation.... vous avez déjà les listes de listes de bs4 et pourriez utiliser csv pour écrire par exemple)

import requests
from bs4 import BeautifulSoup as bs
import pandas as pd

def get_lectures(klasse):
    rows = []
    for row in soup.select(f'.mon_list tr:has(td:nth-of-type(5):contains("{klasse}"))'):
        rows.append([td.text.replace('\xa0','') for td in row.select('td')])
    return rows

r = requests.get('https://niwla23.gitlab.io/download/vertreterdemo.html')
soup = bs(r.content, 'lxml')
headers = [th.text for th in soup.select('th.list')]
klasse = '5b'

df = pd.DataFrame(get_lectures(klasse), columns = headers)
print(df)

1voto

KunduK Points 26770

Essayez le code suivant. Récupérez le texte de la ligne et vérifiez si elle a 5b

from bs4 import BeautifulSoup
import requests
res=requests.get("http://niwla23.gitlab.io/download/vertreterdemo.html")
soup=BeautifulSoup(res.text,'lxml')

for row in soup.find_all('tr', class_='list even'):
    if '5b' in row.text:
        print(row.text)

1voto

MrJuicyBacon Points 161

Vous pouvez trouver tous les tds qui contiennent 5b en utilisant seulement des BS comme ça :

tds_5b = soup.find_all('td', class_='list', text='5b')

et ensuite itérer à travers eux pour trouver un parent tr pour chacun d'entre eux :

out = set()
for row in tds_5b :
    out.add(row.find_parent('tr'))

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X