Как использовать HTMLParser Python для извлечения конкретных ссылок - PullRequest
1 голос
/ 14 марта 2012

Я работал над основным веб-сканером в Python, используя класс HTMLParser.Я получаю свои ссылки с помощью модифицированного метода handle_starttag, который выглядит следующим образом:

def handle_starttag(self, tag, attrs):
    if tag == 'a':
        for (key, value) in attrs:
            if key == 'href':
                newUrl = urljoin(self.baseUrl, value)
                self.links = self.links + [newUrl]

Это сработало очень хорошо, когда я хотел найти каждую ссылку на странице.Теперь я хочу получить только определенные ссылки.

Как мне выбрать только ссылки между тегами <td class="title"> и </td>, например:

<td class="title"><a href="http://www.stackoverflow.com">StackOverflow</a><span class="comhead"> (arstechnica.com) </span></td>

1 Ответ

7 голосов
/ 14 марта 2012

HTMLParser - это синтаксический анализатор в стиле SAX или потоковый анализатор, что означает, что вы получаете фрагменты документа по мере их анализа, но не весь документ сразу. Парсер вызывает предоставляемые вами методы для обработки тегов и других типов данных. Любой контекст, который вас может заинтересовать, например, какие теги находятся внутри других тегов, вы должны найти по тегам, которые видите, проходя мимо.

Например, если вы видите тег <td>, то вы знаете, что находитесь в ячейке таблицы и можете установить флаг для этого эффекта. Когда вы видите </td>, вы знаете, что покинули ячейку таблицы и можете снять этот флаг. Чтобы получить ссылки внутри ячейки таблицы, затем, если вы видите <a> и знаете, что находитесь в ячейке таблицы (из-за установленного вами флага), вы получаете значение атрибута href тега, если он имеет один.

from HTMLParser import HTMLParser

class LinkExctractor(HTMLParser):

    def reset(self):
        HTMLParser.reset(self)
        self.extracting = False
        self.links      = []

    def handle_startag(self, tag, attrs):
        if tag == "td" or tag == "a":
            attrs = dict(attrs)   # save us from iterating over the attrs
        if tag == "td" and attrs.get("class", "") == "title":
            self.extracting = True
        elif tag == "a" and "href" in attrs and self.extracting:
            self.links.append(attrs["href"])

    def handle_endtag(self, tag):
        if tag == "td":
            self.extracting = False

Это быстро становится проблемой, так как вам нужно все больше и больше контекста, чтобы получить то, что вы хотите из документа, именно поэтому люди рекомендуют lxml и BeautifulSoup. Это синтаксические анализаторы в стиле DOM, которые отслеживают иерархию документов и предоставляют различные удобные способы навигации по ним, такие как DOM API, XPath и / или CSS-селекторы.

Кстати, я недавно ответил на похожий вопрос здесь .

...