Como corrigir HTML não compatível tão Expat irá analisá-lo (htmltidy não funciona)

StackOverflow https://stackoverflow.com/questions/1814731

Pergunta

Eu estou tentando informações raspar a partir http://www.nfl.com/scores (em particular, descobrir quando um jogo termina assim que meu computador pode parar de gravar-lo). Eu posso baixar o HTML com bastante facilidade, e isso faz essa afirmação sobre a conformidade com os padrões:

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

Mas

  1. Uma tentativa de analisá-lo com Expat produz o not well-formed (invalid token) erro.

  2. O serviço de validação online do W3C relata 399 Erros e 121 advertências.

  3. Eu tentei correr HTML arrumado (chamado apenas tidy) no meu sistema Linux com a opção -xml, mas os relatórios arrumado 56 advertências e 117 erros e é incapaz de recuperar um arquivo bom XML. Os erros parecido com este:

    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>
    

    Mas quando eu verificar a entrada, as "entidades desconhecidas" parecem ser parte de uma URL corretamente citado, então eu não sei se uma aspa está faltando em algum lugar ou o quê.

Eu sei que há algo lá fora, que pode analisar este material porque tanto Firefox e exibição w3m algo razoável. Que ferramenta irá corrigir o HTML não compatível para que eu possa analisá-lo com Expat?

Foi útil?

Solução

Há uma auto-atualização placar coisa baseado em Flash no topo da nfl.com. Alguns monitoramento de seus achados de tráfego de rede:

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

Isso provavelmente será um pouco mais fácil de analisar do que o placar HTML.

Outras dicas

Eles estão usando algum tipo de Javascript nas caixas de pontuação, então você vai ter que jogar truques mais inteligentes (quebras de linha de minas):

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

No entanto, para responder à sua pergunta, BeautifulSoup analisa-lo (aparentemente) bem:

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]

Saídas:

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

Pode ser mais fácil de raspar NFL placar do Yahoo , na minha opinião ... na verdade , fora de experimentá-lo.


EDIT: Usado sua pergunta como uma desculpa para dar a volta a aprender BeautifulSoup. Alex Martelli foi cantando seu louvor, por isso achei que uma tentativa vale a pena - homem, estou impressionado

.

De qualquer forma, eu era capaz de preparar um raspador de pontuação rudimentar do Yahoo! scoreboard, assim:

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]

Gostaria de ajustar isso no domingo para ver como ele funciona, como é realmente difícil. Aqui está o que ele gera a partir de agora:

--- 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)

Olhe para isso, eu roubado fichas técnicas também ... para um jogo que ainda não aconteceu, temos:

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

De qualquer forma, uma estaca para você saltar de. Boa sorte.

TagSoup . Se você quer acabar com uma árvore DOM ou um fluxo SAX em Java, é o bilhete. Se você quiser apenas para extrair informações específicas, Beautiful Soup é uma coisa bonita.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top