Как избежать длинной цепочки попыток и исключений? - PullRequest
2 голосов
/ 05 июня 2019

Я пытаюсь найти поля поиска на веб-сайтах, используя пакет Python Mechanize для поиска форм на веб-страницах.Практически каждый веб-сайт определяет эти формы по-своему, поэтому мне нужно искать кучу разных подписей.Поскольку функция Mechanize Browser.select_form выдает исключение всякий раз, когда не удается найти указанную форму, поиск множества различных форм превращается в длинный список операторов try и исключением.

Первое, что я попробовал (или свернул), это следующая структура.Это работает, но 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

Возможно, немного лучшим решением было бы направить предложения исключений к функциям, как в 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

Возможно ли что-то похожее на это?

Ответы [ 3 ]

5 голосов
/ 05 июня 2019

Единственное, что является переменной, это имя аргумента ключевого слова, переданное 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')
0 голосов
/ 05 июня 2019

Если вы хотите что-то более общее, вы можете создать класс для каждого из шаблонов поиска, а затем повторить список экземпляров этих классов.

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

Иногда это хорошее решение, а иногда немного лишнее.

Примечание. Я написал этот ответ со своего телефона, код не проверен.

0 голосов
/ 05 июня 2019

Я не уверен насчет механизации, но я знаю, что это возможно с селеном.Более или менее точно как пример, который вы использовали, на самом деле.Я не буду использовать лямбду в этом следующем примере, но он даст тот же эффект чуть медленнее.Предположим, драйвер - это имя указателя переменной для моего браузера.

listOfPossibleFields = ["user", "username", "un", "name", "login"]
for word in listOfPossibleFields:
    try:
        driver.find_element_by_name(word)
    except Exception:
         pass
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...