Проект «Дешевые рейсы» / Элемент Button возвращает ошибку объекта NoneType Selenium python - PullRequest
1 голос
/ 16 июня 2019

Я работаю над небольшим сайленским проектом Selenium, который поможет мне найти дешевые авиабилеты в любое время и в любом месте. У меня проблема с элементом Button. Не могу заставить его работать.

Код: https://github.com/johnnybigH/wizzscrap

from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.support.wait import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
from selenium.webdriver.common.keys import Keys
from selenium.common.exceptions import TimeoutException
from selenium.webdriver.common.action_chains import ActionChains


class wizzScrap:

    def __init__(self, url):
        self.driver = None
        self.url = url
        self.by = None
        self.value = None

        self.web_element = None
        # self.find()


    def setUpDriver(self):
        #  Set up driver
        options = webdriver.ChromeOptions()
        options.add_argument('--ignore-certificate-errors')
        options.add_argument('--no-proxy-server')
        options.add_argument('--incognito')
        prefs = {"profile.default_content_setting_values.geolocation" :2}
        options.add_experimental_option("prefs",prefs)
        self.driver = webdriver.Chrome( 
                "/Users/adamke/Downloads/chromedriver", 
                options=options)
        return self.driver


    def startDriver(self):
        self.driver.get(self.url)


    def find(self, by, value):
        element = WebDriverWait(
            self.driver, 20).until(
            EC.visibility_of_element_located((by, value)))
        self.web_element = element
        return None        


    def inputText(self, text):
        return self.web_element.send_keys(text)


    def click(self, by, value):
        element = WebDriverWait(
            self.driver, 30).until(
            EC.element_to_be_clickable((by, value)))
        self.web_element = element
        element.click()
        return self.web_element


    def text(self):
        text = self.web_element.text
        return text


    def switch_tabs(self):
        #  Close unneded tab and focus on the main one
        WebDriverWait(self.driver, 20).until(
            EC.number_of_windows_to_be(2))

        mainWindow = self.driver.window_handles[1]  #  Thats the Tab we want
        self.driver.close()
        self.driver.switch_to.window(mainWindow)


    def isElementPresent(self, by, value):
        try:
            self.find(by, value)
        except NoSuchElementException:
            result = False
        else: 
            result = True
        print(result)


    def closeDriver(self):
        self.driver.quit()


    def getDestArriv(self):
        #  Choose the Origin and Destination for your fly
        try:
            #  Origin
            self.click(By.XPATH, "//*[@id='search-departure-station']")
            self.inputText('Katowice')
            self.click(By.CSS_SELECTOR, 
            "strong[class='locations-container__location__name']")
            #  Arrival
            self.click(By.XPATH, "//*[@id='search-arrival-station']")
            self.inputText('malaga')
            self.click(By.CSS_SELECTOR, 
            "strong[class='locations-container__location__name']")
            #  Start searching
            self.click(By.CSS_SELECTOR, "button[data-test='flight-search-submit']")
        except Exception:
            print('Thats shitty code man, work on it!')



    def parse(self):
        self.setUpDriver()
        self.startDriver()
        self.getDestArriv()

        # Switch to the Tab that contains tickets prices for next few days
        self.switch_tabs()

        # Button "Next"
        self.isElementPresent(By.XPATH, '//*[@id="outbound-fare-selector"]/div[2]/div[1]/button[2]')
        self.click(By.XPATH, '//*[@id="outbound-fare-selector"]/div[2]/div[1]/button[2]')


url = 'https://wizzair.com'
Page = wizzScrap(url)
Page.parse()
Page.closeDriver()

После выбора аэропортов я переключаюсь на вкладку с ценами на билеты на ближайшие несколько дней. Есть две кнопки «предыдущий» и «следующий». Оба возвращают пустой или NonType.

Это элемент, с которым у меня проблема. xpath для «кнопки далее»:

self.click(By.XPATH, '//*[@id="outbound-fare-selector"]/div[2]/div[1]/button[2]')

Функция «self.isElementPresent» вернула True, поэтому элемент существует.

Я пытался взаимодействовать с ним с помощью .Xpath, CSS_SELECTOR, (x, y location), ActionChain и некоторых других методов, но ничего не работает. Я также получил 96 элементов, выполнив:

button_test = self.driver.find_elements_by_tag_name('button')
    collection_of_buttons = []
    for button in button_test:
        collection_of_buttons.append(button)

    for button in collection_of_buttons:
        print(button)

это то же число, которое я получаю в консоли браузера, поэтому, если я правильно понимаю, ничего не скрыто. Я также попытался выполнить execute_script, но это также не сработало.

У меня больше нет идей, поэтому буду очень признателен за любую помощь.

Ответы [ 2 ]

1 голос
/ 18 июня 2019

Это работает:

self.driver.execute_script("return 
document.getElementsByClassName('flight-select__flight-date-picker__button 
flight-select__flight-date-picker__button--next')[0].click();")
1 голос
/ 17 июня 2019

Ваш метод find всегда возвращает None, следовательно, ошибка 'NoneType' object:

def find(self, by, value):
    element = WebDriverWait(
        self.driver, 20).until(
        EC.visibility_of_element_located((by, value)))
    self.web_element = element
    return None     

Что вам нужно сделать, это вернуть элемент ...

def find(self, by, value):
    element = WebDriverWait(
        self.driver, 20).until(
        EC.visibility_of_element_located((by, value)))
    self.web_element = element
    return self.web_element # or return element

Кроме того, измените XPath для более надежного использования:

# Button "Next"
self.click(By.XPATH, '//button[@class="flight-select__flight-date-picker__button flight-select__flight-date-picker__button--next"]')

Edit:

Вы можете использовать ActionChains для клика со смещением:

button_element = self.find(By.XPATH, '//button[@class="flight-select__flight-date-picker__button flight-select__flight-date-picker__button--next"]')
action = webdriver.common.action_chains.ActionChains(driver)
action.move_to_element_with_offset(button_element, 5, 5).click().perform()

Надеюсь, это поможет вам!

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...