【问题标题】:Abort HTMLParser processing in Python在 Python 中中止 HTMLParser 处理
【发布时间】:2010-12-31 17:52:47
【问题描述】:

在 Python 中使用 HTMLParser 类时,是否可以在 handle_* 函数中中止处理?在处理的早期,我得到了我需要的所有数据,所以继续处理似乎是一种浪费。下面是一个提取文档元描述的示例。

from HTMLParser import HTMLParser

class MyParser(HTMLParser):

    def handle_start(self, tag, attrs):
        in_meta = False
        if tag == 'meta':
          for attr in attrs:
              if attr[0].lower() == 'name' and attr[1].lower() == 'description':
                  in_meta = True
              if attr[0].lower() == 'content':
                  print(attr[1])
                  # Would like to tell the parser to stop now,
                  # since I have all the data that I need

【问题讨论】:

  • 你不应该继承HTMLParser而不是Parser吗?
  • 哦,我真的推荐 BeautifulSoup 来解析 HTML - 它更容易使用
  • 我认为很容易得出结论,这只是一个错字。因为如果不是这个代码将无法工作。
  • @shylent:我并没有暗示这是他的问题的原因 - 因此这是一个评论,而不是一个答案

标签: python html parsing


【解决方案1】:

您可以引发异常并将您的 .feed() 调用包装在 try 块中。

当您决定完成时,您也可以致电self.reset()(我实际上并没有尝试过,但根据documentation“重置实例。丢失所有未处理的数据。”, - 这正是您需要)。

【讨论】:

  • 这里的异常听起来不是个好主意——异常应该只用于异常情况,在这种情况下,您只需建议将其用作控制流工具。至于'reset'方法,我也考虑过,但我不知道它是否真的相关
  • re: "exceptions .. for exception conditions" - 对于 python 来说并非如此。你知道吗,只要迭代器“用完”迭代,就会引发 StopIteration 吗?这算不上什么“特殊情况”,不是吗?事实上,它与提问者想要处理的条件明显相似——一种“立即休息”的条件。
  • @shylent:关于 StopIteration 是真的,但这很少手动处理,而是被包装了,这样用户几乎不会直接看到它。不过,你说得很好。
  • 我正在寻找相同问题的答案,并且喜欢您的解决方案。首先尝试了 self.reset(),因为它似乎是一个专门的解决方案,但它似乎引发了一个异常,带有一些有趣的消息,比如“我们不应该在这里”。现在以解析的数据作为参数引发自定义异常。一个附加的答案和一个例子。
  • handle_starttag 内部调用self.reset() 会引发异常,并带有文本“我们不应该到达这里!” (python 3.5) 我认为你最好注意这一点。
【解决方案2】:

如果您使用 pyparsing 的 scanString 方法,您可以更好地控制您实际通过输入字符串的程度。在您的示例中,我们创建了一个匹配<meta> 标记的表达式,并添加了一个解析操作,以确保我们只将标记与name="description" 匹配。此代码假定您已将页面的 HTML 读入变量 htmlsrc

from pyparsing import makeHTMLTags, withAttribute

# makeHTMLTags creates both open and closing tags, only care about the open tag
metaTag = makeHTMLTags("meta")[0]
metaTag.setParseAction(withAttribute(name="description"))

try:
    # scanString is a generator that returns each match as it is found
    # in the input
    tokens,startloc,endloc = metaTag.scanString(htmlsrc).next()

    # attributes can be accessed like object attributes if they are 
    # valid Python names
    print tokens.content

    # if the attribute name clashes with a Python keyword, or is 
    # otherwise unsuitable as an identifier, use dict-like access instead
    print tokens["content"]

except StopIteration:
    print "no matching meta tag found"

【讨论】:

  • 感谢您的回答。我确信这也有效,我很欣赏对 pyparsing 的一些介绍。如果可以的话,我会标记两者都是正确的。
【解决方案3】:

扩展@shylent 的答案,这是我的解决方案:

class MyParser(HTMLParser):

    boolean_flag = False

    def handle_starttag(self, tag, attrs):
        # for example:
        self.boolean_flag = (tag == "sometag" and ("id", "someid") in attrs)

    def handle_endtag(self, tag):
        pass

    def handle_data(self, data):
        if self.boolean_flag:
            raise DataParsedException(data)


class DataParsedException(Exception):
    def __init__(self, data):
        self.data = data

用法:

try:
    parser.feed(html.decode())
except DataParsedException as dataParsed:
    vars.append(dataParsed.data)

它完成了这项工作。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2012-03-31
    • 1970-01-01
    • 2012-06-19
    • 1970-01-01
    • 2015-02-04
    • 2012-11-18
    • 1970-01-01
    • 2016-06-21
    相关资源
    最近更新 更多