Как исправить несоответствующий HTML-код, чтобы Expat его проанализировал (htmltidy не работает)
-
06-07-2019 - |
Вопрос
Я пытаюсь наскрести информацию из 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">
Но
Попытка разобрать его с помощью Эмигрант выдает ошибку
not well-formed (invalid token)
.В Онлайн-сервис проверки подлинности W3C сообщает о 399 ошибках и 121 предупреждении.
Я попытался запустить 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?
Решение
В верхней части страницы есть функция автоматического обновления табло на основе Flash nfl.com .Некоторый мониторинг его сетевого трафика обнаруживает:
http://www.nfl.com/liveupdate/scorestrip/ss.xml
Вероятно, это будет немного проще разобрать, чем HTML-табло.
Другие советы
Они используют какой-то 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, на мой взгляд...на самом деле, пора попробовать.
Редактировать: Использовал ваш вопрос как предлог, чтобы заняться изучением BeautifulSoup.Алекс Мартелли пел ему хвалу, так что я решил, что стоит попробовать - блин, я впечатлен.
Во всяком случае, я смог приготовить элементарный скребок для подсчета очков от 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(" ", "")
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)
В любом случае, колышек, с которого ты можешь спрыгнуть.Удачи.
Загляни в набор тегов.Если вы хотите в конечном итоге получить DOM-дерево или SAX-поток на Java, это то, что нужно.Если вы просто хотите извлечь конкретную информацию, Красивый суп - это прекрасная вещь.