【问题标题】:Selenium find_element_by_id not returning full elementSelenium find_element_by_id 不返回完整元素
【发布时间】:2021-06-20 22:30:54
【问题描述】:

这对我来说似乎是可疑的行为:

使用 Selenium 和 Chrome webdriver(Ubuntu 20.04 上的 python 3.8.5),我没有从 find_element_by_id 获得完整的 webElement。如果我没有得到任何东西,我会认为是飞行员错误,但我得到了部分元素。

这是我正在使用的代码:

...
driver = webdriver.Chrome(options = chrome_options, executable_path="/usr/bin/chromedriver")
driver.implicitly_wait(20)
driver.get(URL)

inventory_exists = True
try:
    table = driver.find_element_by_id('inventoryTableBody')
    print(table.text) 
except:
    inventory_exists = False
...

这是我希望使用该方法inventoryTableBody 获取的 webElement 的 HTML:

我得到了该组中的前 5 个 DIV,但其余的都是空的。其余的 DIV 都在那里,因为当我在该inventoryTableBody 上使用find_elements_by_class_name('wrapper'),然后使用for w in wrappers 填充字典时,我在该字典上得到一个len(),共10 个。前 5 个填充了数据,但后 5 个(实际上是其余的,因为有时有 12 个,而我仍然只得到前 5 个)完全是空的。我仍然可以遍历它们,并计算它们,但是没有文本。

我有implicitly_wait() 在那里,因为我想确定这不是返回太快的结果。不管the wait()是10秒还是20秒,我仍然只得到前5个子元素。

哦,页面是动态构建的,所以urlopen() 只是获取带有加载占位符的基本 HTML(因此是 Selenium):

<div id="inventoryTableBody">
   <div class="loading">

      <div class="logo-spin "></div>
   </div>
</div>

示例网址为:https://www.lcbo.com/webapp/wcs/stores/servlet/PhysicalStoreInventoryView?langId=-1&storeId=10203&catalogId=10051&productId=65616

【问题讨论】:

  • 可以分享网址吗?
  • 滚动视口中的内容是否会改变哪些项目显示值?
  • 显示此页面的网址
  • 许多页面是"lazy",它们仅在用户滚动页面或单击(子)选项卡或展开元素时加载数据。你必须在代码中做同样的事情。代码必须表现得像真正的用户。
  • 示例 URL 为 lcbo.com/webapp/wcs/stores/servlet/… 页面没有出现惰性...刷新时显示完整表格。

标签: python selenium web-scraping beautifulsoup


【解决方案1】:

当我访问该网站时,有一个语言选择器可以在英语和法语之间进行选择。您会注意到仅当您选择其中一个选项时才会出现滚动。也就是说,我使用以下代码发送 TAB + ENTER 键盘组合,选择其中一种语言,我能够提取所有行。

代码还等待语言选择器 div 不可见,并等待所有 wrapper 元素可见。

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

URL = 'https://www.lcbo.com/webapp/wcs/stores/servlet/PhysicalStoreInventoryView?langId=-1&storeId=10203&catalogId=10051&productId=65616#'

driver = webdriver.Chrome()

driver.get(URL)
ActionChains(driver).send_keys(Keys.TAB).perform()
sleep(1)
ActionChains(driver).send_keys(Keys.ENTER).perform()

WebDriverWait(driver, 20).until(EC.invisibility_of_element_located((By.CLASS_NAME, 'language-selector')))


inventory_exists = True
try:
    WebDriverWait(driver,20).until(EC.visibility_of_all_elements_located((By.CLASS_NAME, 'wrapper')))
    table = driver.find_element_by_id('inventoryTableBody')
    print(table.text)
except TimeoutException:
    inventory_exists = False
except:
    inventory_exists = False
finally:
    driver.quit()

【讨论】:

  • 天才!我什至没有想到 webdriver 永远不会接受一种语言......我只是在比较我的浏览器窗口,它当然有一种接受的语言。谢谢你。
  • 我所做的唯一更改是删除“等到所有 'wrapper' 元素都加载完毕”,因为如果该特定产品上没有库存,页面上就不会有 wrapper 元素,等待会超时并中断。仍然 - 效果很好。再次感谢!
  • 我编辑了答案以捕捉硒 TimeoutException 如你所说。使用裸的 except 从来都不好。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-10-29
  • 2014-12-12
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2022-01-23
相关资源
最近更新 更多