Pregunta

Estoy intentando obtener información de http://www.nfl.com/scores (en particular, averigua cuándo termina un juego para que mi computadora pueda dejar de grabarlo). Puedo descargar el HTML con bastante facilidad, y hace esta afirmación sobre el cumplimiento de las normas:

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
    "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">

Pero

  1. Un intento de analizarlo con Expat produce el error no bien formado (token no válido) .

  2. El El servicio de validación en línea del W3C informa 399 errores y 121 advertencias.

  3. Traté de ejecutar HTML tidy (simplemente llamado tidy ) en mi sistema Linux con la opción -xml , pero tidy informa 56 advertencias y 117 errores y no puede recuperar un buen archivo XML. Los errores se ven así:

    line 409 column 122 - Warning: unescaped & or unknown entity "&role"
    ...
    line 409 column 172 - Warning: unescaped & or unknown entity "&tabSeq"
    ...
    line 1208 column 65 - Error: unexpected </td> in <br>
    line 1209 column 57 - Error: unexpected </tr> in <br>
    line 1210 column 49 - Error: unexpected </table> in <br>
    

    Pero cuando verifico la entrada, las "entidades desconocidas" parece ser parte de una URL correctamente citada, por lo que no sé si falta una comilla doble en algún lugar o qué.

Sé que hay algo por ahí que puede analizar estas cosas porque tanto Firefox como w3m muestran algo razonable. ¿Qué herramienta arreglará el HTML no compatible para que pueda analizarlo con Expat?

¿Fue útil?

Solución

Hay un marcador de actualización automática basado en Flash en la parte superior de nfl.com. Algunos monitoreos de su tráfico de red encuentran:

http://www.nfl.com/liveupdate/scorestrip/ss.xml

Eso probablemente será un poco más fácil de analizar que el marcador HTML.

Otros consejos

Están usando algún tipo de Javascript en los cuadros de puntuación, por lo que tendrás que jugar trucos más inteligentes (saltos de línea míos):

/* box of awesome */
// iscurrentweek ? true;
(new nfl.scores.Game('2009112905','54635',{state:'pre',container:'scorebox-2009112905',
wrapper:'sb-wrapper-2009112905',template:($('scorebox-2009112905').innerHTML),homeabbr:'NYJ',
awayabbr:'CAR'}));

Sin embargo, para responder a su pregunta, BeautifulSoup lo analiza (aparentemente) bien:

fp = urlopen("http://www.nfl.com/scores")
data = ""
while 1:
    r = fp.read()
    if not r:
        break
    data += r
fp.close()

soup = BeautifulSoup(data)
print soup.contents[2].contents[1].contents[1]

Salidas:

<title>NFL Scores: 2009 - Week 12</title>

Podría ser más fácil raspar el marcador de la NFL de Yahoo , en mi opinión ... de hecho ... , fuera para probarlo.


EDITAR: usó su pregunta como una excusa para aprender a aprender BeautifulSoup. Alex Martelli ha estado cantando sus alabanzas, así que pensé que valía la pena intentarlo, hombre, estoy impresionado.

De todos modos, pude cocinar un raspador de puntaje rudimentario del Yahoo! marcador, así:

def main():
    soup = BeautifulSoup(YAHOO_SCOREBOARD)
    on_first_team = True
    scores = []
    hold = None

    # Iterate the tr that contains a team's box score
    for item in soup(name="tr", attrs={"align": "center", "class": "ysptblclbg5"}):
        # Easy
        team = item.b.a.string

        # Get the box scores since we're industrious
        boxscore = []
        for quarter in item(name="td", attrs={"class": "yspscores"}):
            boxscore.append(int(quarter.string))

        # Final score
        sub = item(name="span", attrs={"class": "yspscores"})[0]
        if sub.b:
            # Winning score
            final = int(sub.b.string)
        else:
            data = sub.string.replace("&nbsp;", "")
            if ":" in data:
                # Catch TV: XXX and 0:00pm ET
                final = None
            else:
                try: final = int(data)
                except: final = None

        if on_first_team:
            hold = { team : (boxscore, final) }
            on_first_team = False
        else:
            hold[team] = (boxscore, final)
            scores.append(hold)
            on_first_team = True

    for game in scores:
        print "--- Game ---"
        for team in game:
            print team, game[team]

Me gustaría ajustar esto el domingo para ver cómo funciona, ya que es realmente difícil. Esto es lo que muestra en este momento:

--- Game ---
Green Bay ([0, 13, 14, 7], 34)
Detroit ([7, 0, 0, 5], 12)
--- Game ---
Oakland ([0, 0, 7, 0], 7)
Dallas ([3, 14, 0, 7], 24)

Mira eso, también obtuve puntajes de caja ... para un juego que aún no ha sucedido, obtenemos:

--- Game ---
Washington ([], None)
Philadelphia ([], None)

De todos modos, una clavija para que saltes. Buena suerte.

Examine tagsoup . Si desea terminar con un árbol DOM o una secuencia SAX en Java, es el ticket. Si solo desea extraer información específica, Beautiful Soup es una cosa hermosa.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top