Domanda

Sto cercando di raccogliere informazioni da http://www.nfl.com/scores (in particolare, scopri quando un gioco è finito in modo che il mio computer possa interrompere la registrazione). Riesco a scaricare l'HTML in modo abbastanza semplice, e fa questa affermazione sulla conformità agli standard:

<!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">

Ma

  1. Un tentativo di analizzarlo con Expat produce l'errore non ben formato (token non valido) .

  2. Il il servizio di validazione online del W3C riporta 399 errori e 121 avvisi.

  3. Ho provato a eseguire HTML tidy (appena chiamato tidy ) sul mio sistema Linux con l'opzione -xml , ma tidy riporta 56 avvisi e 117 errori e non è in grado di recuperare un buon file XML. Gli errori si presentano così:

    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>
    

    Ma quando controllo l'input, le "entità sconosciute" sembrano far parte di un URL correttamente citato, quindi non so se manca una doppia citazione da qualche parte o cosa.

So che c'è qualcosa che può analizzare queste cose perché sia ??Firefox che w3m mostrano qualcosa di ragionevole. Quale strumento risolverà l'HTML non conforme in modo da poterlo analizzare con Expat?

È stato utile?

Soluzione

Nella parte superiore di nfl.com è presente un tabellone di aggiornamento automatico basato su Flash. Alcuni controlli del suo traffico di rete rilevano:

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

Probabilmente sarà un po 'più semplice analizzare il quadro di valutazione HTML.

Altri suggerimenti

Stanno usando una sorta di Javascript nelle caselle dei punteggi, quindi dovrai giocare più acrobazie (le mie interruzioni di riga):

/* 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'}));

Tuttavia, per rispondere alla tua domanda, BeautifulSoup la analizza (apparentemente) bene:

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]

Uscite:

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

Potrebbe essere più semplice raschiare tabellone segnapunti NFL di Yahoo , secondo me ... in effetti , via per provarlo.


MODIFICA: hai usato la tua domanda come scusa per imparare a imparare BeautifulSoup. Alex Martelli ha cantato le sue lodi, quindi ho pensato che valesse la pena provarlo - amico, sono impressionato.

Ad ogni modo, sono stato in grado di cucinare un raschietto rudimentale del punteggio da Yahoo! tabellone segnapunti, in questo modo:

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]

Lo vorrei modificare domenica per vedere come funziona, dato che è davvero approssimativo. Ecco cosa produce in questo 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)

Guarda, ho anche preso i punteggi delle caselle ... per un gioco che non è ancora successo, otteniamo:

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

Ad ogni modo, un piolo da cui saltare. Buona fortuna.

Guarda tagsoup . Se vuoi finire con un albero DOM o un flusso SAX in Java, è il ticket. Se vuoi solo estrarre informazioni specifiche, Beautiful Soup è una cosa meravigliosa.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top