漂亮的错误处理美丽汤中的缺少字段

时间:2014-12-09 14:05:19

标签: python web-scraping beautifulsoup

我在使用Beautifulsoup抓取一些页面时遇到了相当多的错误,主要是因为某些页面在HTML中略有不同或实际上缺少字段。

我正在寻找一种干净的方法来处理这些问题,但我还没有找到文档或其他问题中的一个。我目前正在使用try,except子句为每个字段处理这个,因为我仍然想要检索剩余字段(如果缺少一个字段)。

try:
    address = house.find(text=re.compile('[0-9]{4}[ ]?[azAZ]{2}'))
except:
    address = "ERR No Address"

然而,这导致许多尝试除了子句,我想知道在保持代码可读的同时处理这个问题的更好方法是什么?

编辑:回答凯文的回答:功能确实是我正在寻找的,但我有以下问题:

着眼于可扩展性,我如何创建一个不仅接受上述查找调用而且接受任何查找调用的函数?我需要捕获以下调用,例如:

house.find("a", class_='object-street').text)
house.find("a", class_='object-street').attrs['href']
house.find('span', title=re.compile('Number of')).text
house.find("span", title="WaitingFor").text

我想我正在寻找一个'包装',但没有经验。非常感谢任何正确方向的提示!

1 个答案:

答案 0 :(得分:2)

创建一个尝试查找文本的函数,而不是引发错误,返回字符串错误消息。

def safe_find(element, text, error_message):
    try:
        return element.find(text=re.compile(text))
    except:
        return error_message

然后,您可以使用此函数检索可能缺少的字段,而不使用任何内联try-except子句。

address = safe_find(house, '[0-9]{4}[ ]?[azAZ]{2}', "ERR No Address")

编辑:您可以使函数稍微更具可扩展性,接受find可能采用的任何参数:

def safe_find(element, error_message, *args, **kargs):
    try:
        return element.find(*args, **kargs)
    except:
        return error_message

safe_find(house, "ERR No Address", text=re.compile('[0-9]{4}[ ]?[azAZ]{2}'))
safe_find(house, "ERR no street", "a", class_='object-street')
safe_find(house, "ERR no street", "a", class_='object-street')
safe_find(house, "ERR no number", 'span', title=re.compile('Number of'))
safe_find(house, "ERR no WaitingFor", "span", title="WaitingFor")

...但您无法使用它来访问任何属性,例如textattrs['href']


编辑编辑:您可以创建一个特殊对象,其中包含您可能想要访问的所有属性的错误消息。

import collections
def safe_find(element, error_message, *args, **kargs):
    class FakeResult:
        def __init__(self, err):
            self.attrs = collections.defaultdict(lambda: err)
            self.text = err
            #todo: add other attributes here, like:
            #self.whatever = err
    try:
        return element.find(*args, **kargs)
    except:
        return FakeResult(error_message)

safe_find(house, "ERR no street", "a", class_='object-street').text
safe_find(house, "ERR no street", "a", class_='object-street').attrs['href']
safe_find(house, "ERR no number", 'span', title=re.compile('Number of')).text
safe_find(house, "ERR no WaitingFor", "span", title="WaitingFor").text

但是,如果您要访问textattrs属性,则此有效。 safe_find(house, "ERR No Address", text=re.compile('[0-9]{4}[ ]?[azAZ]{2}'))后面没有.text.attrs["stuff"]会为您提供FakeResult实例而不是字符串。