【问题标题】:Selenium: How to load invisible elements of a dropdown menu (Python)Selenium:如何加载下拉菜单的不可见元素(Python)
【发布时间】:2020-03-31 16:51:25
【问题描述】:

我最近一直在练习我的网络抓取技巧,并偶然发现了 Fábio Neves 的这篇精彩作品:If you like to travel, let Python help you scrape the best cheap flights!

我决定尝试创建一个机器人来抓取Ryanair site,而不是像 Fábio 那样抓取“Kayak”网站。

我的做法:

我接受用户输入的“出发机场”。然后我选择提示下拉列表出现的“发件人”文本框。此下拉列表包含 234 个位置。

city_from = input('From which city? ') #Takes users input

我尝试实施的下一步是使用下拉列表中的选项查找用户输入的匹配项。然后继续单击该匹配选项。

elements_list = driver.find_elements_by_xpath('//div [@class="core-list-ref"]') ##Finds all Elements/Cities in the dropdown list

list_pos = [value for value in elements_list].index(str(city_from)) #Finds the value(city name) for each element in the dropdown list and tries to locate the position of the inputed 'airport of departure' in the list.

elements_list[list_pos].click() #I then try to select this option.

不过……

我用下面的代码好像不是所有的234个城市都出现了:

driver.find_elements_by_xpath('//div [@class="core-list-ref"]')

只有前 79 个城市出现在奥尔堡-热那亚,其他城市似乎是“隐藏的”。我发现当我手动向下滚动到下拉列表的底部并尝试重新运行它们出现的代码时。 于是我尝试实现.move_to_element(element),让机器人向下滚动到下拉列表中的最后一个机场。但这仍然只允许我滚动到第 79 机场(热那亚)。当用户输入像“苏黎世”这样的机场时,这会使我的机器人崩溃。

这是我第一次尝试抓取。我该如何克服这个问题,或者有更好的方法来选择“出发机场”。如果您需要更多详细信息,请告诉我。

【问题讨论】:

    标签: python selenium web-scraping jupyter-notebook


    【解决方案1】:

    请找到以下解决方案:

    from selenium import webdriver
    from selenium.webdriver.common.keys import Keys
    from selenium.webdriver.support import expected_conditions as EC
    from selenium.webdriver.common.by import By
    from selenium.webdriver.support.ui import WebDriverWait
    from selenium.webdriver.common.action_chains import ActionChains
    
    
    driver = webdriver.Chrome(executable_path=r"C:\New folder\chromedriver.exe")
    driver.maximize_window()
    wait = WebDriverWait(driver, 20)
    driver.get("https://www.ryanair.com/ie/en/cheap-flights/?from=DUB&out-from-date=2020-03-31&out-to-date=2021-03-31&budget=150")
    inputBox = wait.until(EC.element_to_be_clickable((By.XPATH, "//div[@name='departureInput']//div[@class='disabled-overlay']")))
    
    actionChains = ActionChains(driver)
    actionChains.move_to_element(inputBox).click().perform()
    
    list = wait.until(EC.presence_of_all_elements_located((By.XPATH, "//div[@class='core-list']")))
    
    for element in list:
         print element.text
    

    输出:

    【讨论】:

      【解决方案2】:

      如果您一直向下滚动 From 列表,您将看到有 256 个元素与您在问题 //div [@class="core-list-ref"] 中提到的 xpath 匹配,其中只有 253 个是独特的机场(仔细查看开发控制台,你会看到我在说什么)。 为了解决这个问题,并且为了创造性,下面是解决问题的不同角度 - 从地图视图中获取所有机场。

      WebDriverWait(driver,20).until(EC.element_to_be_clickable((By.XPATH,"//*[@icon-id='glyphs.earth']")))
      driver.find_element_by_xpath("//*[@icon-id='glyphs.earth']").click() #click Map View
      
      WebDriverWait(driver,20).until(EC.element_to_be_clickable((By.CLASS_NAME,"airports")))
      airports_root=driver.find_element_by_class_name('airports')
      airport_tags=airports_root.find_elements_by_tag_name('text')
      
      airport_names=[]
      for airport in airport_tags:
          airport_names.append(airport.get_property('innerHTML'))
      

      请注意,这些是机场名称,不一定与城市名称相同,例如输入“Murcia”,它会自动完成“Murcia International”。

      您可以将您的用户输入与此列表进行比较(避免 == 由于上述注释以及其他原因)以确保其有效,然后将其输入到 From/To 字段中。注意下面的代码不包括数据验证检查:

      #From
      valid_city_from = input('From which city? ')
      departure=driver.find_element_by_xpath("//div[@name='departureInput']//div[@class='disabled-wrap']/input")
      driver.execute_script("arguments[0].value = '"+ valid_city_from + "';", departure)
      
      # To
      valid_city_to = input('To which city? ')
      destination=driver.find_element_by_xpath("//div[@name='destinationInput']//div[@class='disabled-wrap']/input")
      driver.execute_script("arguments[0].value = '"+ valid_city_to + "';", destination)
      

      顺便说一句,WebdriverWait 需要这些导入:

      from selenium.webdriver.common.by import By
      from selenium.webdriver.support.ui import WebDriverWait
      from selenium.webdriver.support import expected_conditions as EC
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2018-11-04
        • 2014-11-26
        • 2016-11-27
        • 2023-03-16
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2016-07-18
        相关资源
        最近更新 更多