【问题标题】:How to avoid long chain of try and except statements?如何避免长链的 try 和 except 语句?
【发布时间】:2019-06-05 08:14:32
【问题描述】:

我正在尝试使用 Mechanize python 包在网站上查找搜索框,以在网页上查找表单。几乎每个网站都以自己的方式定义这些表格,所以我需要搜索一堆不同的签名。因为 Mechanize Browser.select_form 函数在找不到指定表单时会抛出异常,因此查找许多不同的表单会变成一长串 try 和 except 语句。

我尝试(或卷入)的第一件事是以下结构。它可以工作,但是 1:它看起来不太好,2:扩展不好(如果我需要更多的语句,这会变成混乱)和 3:总的来说,这看起来像是糟糕的代码。

from mechanize import Browser
br = Browser()
br.open(url)
try:
    br.select_form(id=lambda x: 'search' in x)
except Exception:
    try:
        br.select_form(class_=lambda x: 'search' in x)
    except Exception:
        try:
            br.select_form(action=lambda x: 'search' in x)
        except Exception:
            try:
                br.select_form(role=lambda x: 'search' in x)
            except Exception:
                print('NOTHING FOUND')
                pass

一个可能稍微好一点的解决方案是将except子句指向函数,如https://stackoverflow.com/a/6095782/11309912。这将解决横向扩展,但仍然包含大量重复代码。

对我来说,理想的解决方案是拥有一个可以迭代的语句列表,直到找到一种类型的表单。一个非常粗略的例子是:

forms = ['id=lambda x: 'search' in x', 'class_=lambda x: 'search' in x', .....]
for form in forms:
    try:
        br.select_form(form)
        break
    except Exception:
        pass

有类似的可能吗?

【问题讨论】:

    标签: python exception


    【解决方案1】:

    唯一可变的是传递给select_form的关键字参数的名称,您可以像这样传递变量关键字:

    for attr in ('id', 'search', 'class_', 'role'):
        try:
            form = br.select_form(**{attr: lambda x: 'search' in x})
            break
        except:
            pass
    else:
        print('NOTHING FOUND')
    

    【讨论】:

    • 处理一个简单的Exception 而不是正确的异常,比如except ValueError:(例如),这不是坏事吗?
    • 当然,您应该在此处捕获特定错误。 OP 正在捕获Exception,这同样糟糕,所以我完全省略了它。我不确定select_form 会准确引发哪些异常,因此无法填写该部分。
    【解决方案2】:

    如果您想要更通用的东西,您可以为每个搜索模式创建一个类,然后迭代思考这些类实例的列表。

    class IdSearchPattern(object):
        def search(self, *args, **kwargs):
            ...
    
    class RoleSearchPattern(object):
        def search(self, *args, **kwargs):
            ...
    
    search_patterns = [IdSearchPattern(), RoleSearchPattern()]
    for sp in search_patterns:
        try:
            result = sp.search()
            break
        except Exception:
            pass
    

    有时这是一个很好的解决方案,有时它有点过度设计。

    注意:我用手机写了这个答案,代码未经测试。

    【讨论】:

      【解决方案3】:

      我不确定机械化,但我知道硒是可能的。实际上,或多或少与您使用的示例完全相同。在下一个示例中我不会使用 lambda,但它会产生相同的效果,但速度会慢一些。假设驱动程序是我的浏览器的变量指针名称。

      listOfPossibleFields = ["user", "username", "un", "name", "login"]
      for word in listOfPossibleFields:
          try:
              driver.find_element_by_name(word)
          except Exception:
               pass
      

      【讨论】:

      • 谢谢,@Arne!我在移动设备上,尽我所能尝试,我总是错过这样的自动大写。
      • 乐于助人 =)
      猜你喜欢
      • 2014-08-23
      • 1970-01-01
      • 2020-11-26
      • 2011-09-29
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-06-08
      • 1970-01-01
      相关资源
      最近更新 更多