Получить HTML-ссылки в пределах указанной <таблицы>, используя minidom

Я хочу использовать Python и xml.dom.minidom, чтобы получить список ссылок в пределах определенного <table> определяется идентификатором таблицы. Основываясь на некоторых отличных советах, я пытаюсь использовать DOM вместо сопоставления с образцом.

import urllib
import xml.dom.minidom

url = 'http://www.batstrading.com/market_data/shortsales'
page = xml.dom.minidom.parse(urllib.urlopen(url))

Я могу получить все ссылки по имени тега page.getElementsByTagName('a'), но я не могу ограничить ссылки, возвращаемые только содержащимися в таблице ссылками с идентификатором "month-short-sale". С помощью getElementById Возвращает None.

Это связано с тем, что идентификатор "ежемесячная короткая продажа" не определен в DTD? Если это так, что будет лучшим способом извлечь эту информацию?

Вот код, который я сейчас использую, который работает, но грешит против Бога:

import urllib
import xml.dom.minidom
import datetime

url = 'http://www.batstrading.com/market_data/shortsales'

def getDownloadLink(alink, prefix = 'BATSsh'):
    """return (datetime.date, link) for the provided link if the link
    target starts with the data file prefix"""

    n = len(prefix)
    href = alink.getAttribute('href')
    if href.startswith(prefix) and (len(href) == 25):
        year = int(href[n:n+4])
        month = int(href[n+4:n+6])
        day = int(href[n+6:n+8])
        date = datetime.date(year, month, day)
        return (date, url + '/' + href)

page = xml.dom.minidom.parse(urllib.urlopen(url))
link = (getDownloadLink(a) for a in page.getElementsByTagName('a'))
link = dict(i for i in link if i is not None)

2 ответа

Решение

Проблема в том, что minidom - это синтаксический анализатор не для чтения внешних объектов. Это означает, что он даже не смотрит на DTD, поэтому он не знает, что в HTML атрибут с именем id соответствует ID тип схемы.

Еще одним следствием этого является то, что minidom не будет знать о таких HTML-объектах, как &eacute; которые определены в типе XHTML, так что вы можете потерять текст таким образом.

Если вас это не волнует, вы можете продолжить использовать минидом и использовать альтернативный способ получить за столом, включая getElementsByTagName и проверка element.id вручную. (Вы можете взломать свой собственный getElementById функция, чтобы сделать это медленным способом.)

Или вы можете использовать синтаксический анализатор XML, который разрешает внешние объекты, такие как pxdom. Однако это означает, что синтаксический анализатор должен будет каждый раз получать и анализировать DTD из W3, что будет неприятно медленным.

Или вы можете использовать синтаксический анализатор HTML, в который встроены сущности HTML и идентификаторы ID, например BeautifulSoup. Это может быть лучшей идеей, когда вы имеете дело с реальными HTML-страницами, которые служат text/html, хотя они могут утверждать, что они XHTML, часто включают в себя непослушные биты, которые не имеют правильной формы.

Я думаю, что вы хотите сначала найти элемент TABLE, а затем вызвать getElemenetByTagName для него. Это должно вернуть все дочерние элементы элемента таблицы. Кроме того, дважды проверьте, что ваш HTML является XHTML; minidom предназначен для разбора XML, а не HTML.

Другие вопросы по тегам