我在使用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
我想我正在寻找一个'包装',但没有经验。非常感谢任何正确方向的提示!
答案 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")
...但您无法使用它来访问任何属性,例如text
或attrs['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
但是,如果您要访问text
或attrs
属性,则此仅有效。 safe_find(house, "ERR No Address", text=re.compile('[0-9]{4}[ ]?[azAZ]{2}'))
后面没有.text
或.attrs["stuff"]
会为您提供FakeResult实例而不是字符串。