HTML-анализатор Python - PullRequest
       5

HTML-анализатор Python

3 голосов
/ 04 ноября 2011

Я пытаюсь разобрать сайт. Я использую модуль HTMLParser. Проблема в том, что я хочу разобрать первый <a href=""> после комментария: <!-- /topOfPage -->, но я не знаю, как это сделать. Итак, я нашел в документации, что есть функция, которая называется handle_comment, но я не нашел, как правильно ее использовать. У меня есть следующее:

import HTMLParser

class LinkFinder(HTMLParser.HTMLParser):
def __init__(self, *args, **kwargs):
    # Can't use super() - HTMLParser is an old-style class
    HTMLParser.HTMLParser.__init__(self, *args, **kwargs)
    self.in_linktag = False
    self.url_cache = []
def handle_comment(self,data):
    if data == "topOfPage":
        print data
def handle_starttag(self, tag, attrs):
    if tag == "a" and any("href" == t[0] for t in attrs): # found link
        self.in_linktag = True
        self.url_cache.append([dict(attrs)['href']])
def handle_endtag(self, tag):
    if tag == "a" and self.in_linktag: # ignore '<a name=""...'
        self.in_linktag = False
def handle_data(self, data):
    if self.in_linktag:
        self.url_cache[-1].append(data)
TESTDATA = """
< html>
< body>
< div>
 < ul>
    < !-- /topOfPage --> 
< tr >
    < td class="empty-cell-left">&nbsp;</td>
    < td class="image">


    < a  href="http://test" rel="nofollow">
 < ul>
< /div>
< /body>
 < /html>
"""
def main():
lf = LinkFinder()
lf.feed(TESTDATA)
lf.close()
print lf.url_cache
if __name__ == "__main__":
    main()

Как это сделать?

Ответы [ 2 ]

2 голосов
/ 04 ноября 2011

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

def __init__(self, *args, **kwargs):
    # ...
    self.first_link_after_comment = False

Затем, когда вы сталкиваетесь с комментарием, флаг должен быть переключен.

def handle_comment(self, data):
    if data.strip() == '/topOfPage':
        self.first_link_after_comment = True

Когда вы обрабатываете открывающий тег, вы должны обязательно пропустить его, если синтаксический анализ не прошел за комментарий

def handle_starttag(self, tag, attrs):
    if not self.first_link_after_comment:
        return
    # ...

И наоборот, когда вы обрабатываете закрывающий тег, вы хотите подтвердить, что миссия выполнена.

def handle_endtag(self, tag):
    if tag == 'a' and self.in_linktag: # ignore '<a name=""...'
        self.in_linktag = False
        self.first_link_after_comment = False

Наконец, когда вы добавляете данные, просто убедитесь, что это не просто строка, которая пуста или содержит только пробелы.

def handle_data(self, data):
    if self.in_linktag and data.strip():
        self.url_cache[-1].append(data)

А вот и вы.

$ your_script.py
[['http://test']]
1 голос
/ 04 ноября 2011

handle_comment возвращает все данных между разделителями.

В этом примере на самом деле данными будет "/ topOfPage" (обратите внимание на пробелы и /).

Вы также можете сделать это вместо:

def handle_comment(self,data):
    if "topOfPage" in data:
        print data
...