首页 > 解决方案 > 廉价航班项目/按钮元素返回“NoneType”对象错误 Selenium python

问题描述

我正在做一个小的 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()

选择机场后,我将切换到包含接下来几天机票价格的选项卡。有“上一个”和“下一个”两个按钮。两者都返回空或非类型。

这是我有问题的元素。 “按钮下一步”的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,但效果不佳。

我没有更多的想法,所以非常感谢任何帮助。

标签: pythonselenium

解决方案


您的方法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"]')

编辑:

您可以使用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()

希望这对你有帮助!


推荐阅读