Как исправить несоответствующий HTML, чтобы Expat проанализировал его (htmltidy не работает)

Я пытаюсь получить информацию с http://www.nfl.com/scores (в частности , узнать, когда игра закончилась, чтобы мой компьютер мог остановить ее запись). Я могу достаточно легко загрузить HTML, и он заявляет о соответствии стандартам:

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

Но

  1. Попытка разобрать его с помощью Expat приводит к ошибке not well-formed (invalid token).

  2. служба онлайн-проверки W3C сообщает о 399 ошибках и 121 предупреждении.

  3. Я попытался запустить HTML tidy (только что названный tidy) в своей системе Linux с параметром -xml, но tidy сообщает о 56 предупреждениях и 117 ошибках и не может восстановить хороший файл XML. Ошибки выглядят так:

    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>
    

    Но когда я проверяю ввод, «неизвестные объекты» кажутся частью правильно цитируемого URL-адреса, поэтому я не знаю, отсутствует ли где-то двойная кавычка или что.

Я знаю, что существует что-то, способное разобрать этот материал, потому что и Firefox, и w3m отображают что-то разумное. Какой инструмент исправит несоответствующий HTML-код, чтобы я мог проанализировать его с помощью Expat?


person Norman Ramsey    schedule 29.11.2009    source источник
comment
wtf это эмигрант? какой-то парень, который живет за границей?   -  person JohnIdol    schedule 29.11.2009
comment
Вы пробовали службу проверки w3c? --› validator.w3.org/#validate_by_input   -  person JohnIdol    schedule 29.11.2009
comment
Expat — это библиотека для разбора XML.   -  person Matthew Scharley    schedule 29.11.2009
comment
Мне неприятно это говорить, но этот HTML — ужасная мешанина, и я был бы очень удивлен, если бы вам удалось заставить его что-то анализировать.   -  person Matthew Scharley    schedule 29.11.2009
comment
Также, re: первые две ошибки. Значения внутри HTML-атрибутов должны быть закодированы. & должно быть &amp;, это обычная проблема в атрибутах href.   -  person Matthew Scharley    schedule 29.11.2009
comment
@johnIdol: хорошая мысль! Я проверил, и он сообщает о многих, многих ошибках --- добавил информацию к вопросу выше.   -  person Norman Ramsey    schedule 29.11.2009
comment
@ Мэтью: Интересно. К сожалению, я сомневаюсь, что смогу заставить Национальную футбольную лигу исправиться. Отсюда вопрос.   -  person Norman Ramsey    schedule 29.11.2009
comment
У кого-то в НФЛ есть чувство юмора (найдено в источнике): /* box of awesome */   -  person Jed Smith    schedule 29.11.2009
comment
@Norman: Тогда вам нужна библиотека для синтаксического анализа HTML, а не XML. Парсеры HTML спроектированы таким образом, чтобы их можно было сломать и выжить.   -  person Matthew Scharley    schedule 29.11.2009


Ответы (3)


В верхней части сайта nfl.com есть функция автоматического обновления таблицы результатов на основе Flash. Некоторый мониторинг его сетевого трафика находит:

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

Это, вероятно, будет немного легче анализировать, чем табло HTML.

person rtucker    schedule 29.11.2009
comment
Очень умно, и действительно легче разобрать. Интересно, не приведет ли это к гонке вооружений? - person Jed Smith; 30.11.2009
comment
На самом деле это не отвечает на поставленный вопрос, но это было настолько полезно для моей реальной проблемы, что я отметил его как принятый ответ. Спасибо!!!!!! - person Norman Ramsey; 19.12.2009

Они используют какой-то Javascript в полях для очков, поэтому вам придется проделывать более хитрые трюки (моя разрывается):

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

Однако, чтобы ответить на ваш вопрос, BeautifulSoup анализирует его (по-видимому) нормально:

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]

Выходы:

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

На мой взгляд, было бы проще очистить табло Yahoo NFL... попытайся.


РЕДАКТИРОВАНИЕ: Ваш вопрос использовался как предлог для изучения BeautifulSoup. Alex Martelli восхваляет его, поэтому я решил, что стоит попробовать — чувак, я впечатлен.

Как бы то ни было, я смог состряпать элементарный скребок для счета с Yahoo! табло, например:

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]

Я бы настроил это в воскресенье, чтобы посмотреть, как это работает, так как это действительно грубо. Вот что он выводит на данный момент:

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

Взгляните на это, я тоже получил очки... для игры, которая еще не состоялась, мы получаем:

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

Во всяком случае, колышек для вас, чтобы спрыгнуть. Удачи.

person Jed Smith    schedule 29.11.2009
comment
BeautifulSoup выглядит потрясающе! +1 - person Norman Ramsey; 30.11.2009
comment
Я проверил это, и BeautifulSoup почти полностью очищает HTML, но XML, который он выдает, по-прежнему содержит 5 ошибок. (Это с выводом с использованием метода prettify.) Я немного не хочу слишком углубляться в суп, так как остальная часть моей инфраструктуры находится на Lua, поэтому я, вероятно, сначала попробую XML-канал. Но об этом все равно стоит знать. - person Norman Ramsey; 30.11.2009

Загляните в tagsoup. Если вы хотите получить дерево DOM или поток SAX в Java, это билет. Если вы просто хотите извлечь конкретную информацию, Beautiful Soup — это Beautiful Thing.

person bmargulies    schedule 29.11.2009
comment
Выглядит действительно полезно, хотя пакет Debian не запускается. Грррр. +1, спасибо. - person Norman Ramsey; 30.11.2009
comment
Как правило, я никогда не использую Java через Debian. - person bmargulies; 30.11.2009