Estoy tratando de familiarizarme con bs4, sin embargo, tengo algunos problemas para extraer información del siguiente html:

<table border="1" cellspacing="0" class="browser">
<thead>..</thead>
<tbody class="body">
<tr class="date">..</tr>
<tr class="right">..</tr>
<tr class="right">..</tr>
<tr class="right">..</tr>
<tr class="date">..</tr>
<tr class="right">..</tr>
<tr class="right">..</tr>
<tr class="right">..</tr>
</tbody>
</table>

Entonces, lo que me gustaría tener es el contenido (class) entre los dos date classes así:

<tr class="date">..</tr>
<tr class="right">..</tr>
<tr class="right">..</tr>
<tr class="right">..</tr>

Y,

<tr class="date">..</tr>
<tr class="right">..</tr>
<tr class="right">..</tr>
<tr class="right">..</tr>

He intentado hacer:

xx = soup.find_all('tbody',{'class':'body'})

Y para obtener el right classes correspondiente hago:

yy = []
for i in xx:
    yy.append( i.find_all('tr',{'class':'right'}) )

... pero esto me da todo el right classes, pero de alguna manera me gustaría establecer cuál es la clase padre date para cada uno de estos elementos en yy. En pocas palabras, me gustaría que cada uno de los right classes asociado con su parent date class

Lo siento de antemano si la pregunta parece confusa!

0
AJW 5 sep. 2014 a las 18:08

2 respuestas

La mejor respuesta

Puede iterar sobre next_siblings hasta que encuentre algo que tenga date nuevamente como clase:

for date_row in soup.select('table tbody.body tr.date'):
    for elem in date_row.next_siblings:
        if not elem.name:
            # NavigableString (text) element between rows
            continue
        if 'right' not in elem.get('class', []):
            # all done, found a row that doesn't have class="right"
            break

Puede recopilarlos en una lista o simplemente procesarlos en el bucle de vez en cuando.

Demo:

>>> for date_row in soup.select('table tbody.body tr.date'):
...     print('Found a date row', date_row)
...     for elem in date_row.next_siblings:
...         if not elem.name:
...             # NavigableString (text) element between rows
...             continue
...         if 'right' not in elem.get('class', []):
...             # all done, found a row that doesn't have class="right"
...             break
...         print('Right row grouped with the date', elem)
...     print()
... 
Found a date row <tr class="date">..</tr>
Right row grouped with the date <tr class="right">..</tr>
Right row grouped with the date <tr class="right">..</tr>
Right row grouped with the date <tr class="right">..</tr>

Found a date row <tr class="date">..</tr>
Right row grouped with the date <tr class="right">..</tr>
Right row grouped with the date <tr class="right">..</tr>
Right row grouped with the date <tr class="right">..</tr>
0
Martijn Pieters 5 sep. 2014 a las 15:51

Tendrá que iterar sobre los elementos secundarios de la etiqueta tbody. Esto funcionará:

# Get just the tags
tags = filter( lambda x: x != '\n', soup.tbody.contents)
collected_tags = []
latest_date = None
for tag in tags:
    if tag['class'] == ['date']:
        date_map = {tag: []}
        collected_tags.append(date_map)
        latest_date = tag
        continue
    if collected_tags and tag['class'] == ['right']:
        collected_tags[-1][latest_date].append(tag)

`` `

collected_tags ahora es una lista de diccionarios que asignan las etiquetas date a las etiquetas right.

1
talumbau 5 sep. 2014 a las 14:45