Selenium - 获取其关联的 Web 元素的标签不断变化的信息
Selenium - Fetching Information Whose Associated Web Element's Tag Keeps Changing
给定一个搜索词,我试图获取亚马逊上 Books 类别下的结果,并获取给定搜索词的每本书的详细信息。
我 运行 遇到一个问题,有时我的代码能够找到结果,有时却失败了。进一步检查后,我意识到这些项目有时会用 <li>
标签列出,有时会用 <div>
标签列出。
下面粘贴的是同一元素的元素和代码片段,以支持我的声明。
HTML 带有 <li>
标签:
<li id="result_0" data-asin="0128023074" class="s-result-item celwidget ">
HTML 带有 <div>
标签:
<div data-asin="0128023074" data-index="0" class="sg-col-20-of-24 s-result-item sg-col-0-of-12 sg-col-28-of-32 sg-col-16-of-20 sg-col sg-col-32-of-36 sg-col-12-of-16 sg-col-24-of-28" data-cel-widget="search_result_0"><div class="sg-col-inner">
我仍然是 Selenium 的新手,所以为了解决这个问题,我使用了以下代码片段,我很确定有更好的方法来处理这个问题。
try:
book = WebDriverWait(driver, 10).until(EC.visibility_of_element_located((By.ID, "result_0")))
book_detail(book, details)
except TimeoutException:
book = WebDriverWait(driver, 10).until(EC.visibility_of_element_located((By.XPATH, "//div[@data-index=\"0\" and @data-cel-widget=\"search_result_0\"]")))
book_detail_by_div(book, details)
谁能帮我理解为什么关联的标签会发生这样的变化,以及如何处理这样的情况?
关于你的第一个问题,为什么会这样,我不确定。我尝试了不同的 OS/Browser 和 window 大小,但无法重现 div
元素的大小写。
为了改进你的代码,我有一个建议,但它可能不是最适合你的解决方案,所以你可以试试。这将等待两种类型的元素中的任何一种一起可见,而不是等待 10 秒第一种然后第二种。
try:
book = WebDriverWait(driver, 10).until(EC.visibility_of_element_located((By.XPATH, '//*[(@id="result_0") or (@data-index="0" and @data-cel-widget="search_result_0")]')))
except TimeoutException:
print("Did not find search result")
else:
# So atleast one of the tag type is visible.
# Even if the attribute is not present then it will return None.
if book.get_attribute('id') == "result_0":
book_detail(book, details)
else:
book_detail_by_div(book, details)
我遵循了问题中提供的详细信息,并在 https://www.amazon.com
搜索文本 The Data and Analytics playbook 时显示了相同的元素。
所以,您对 <div>
标签的观察是正确的。但是我没有在搜索结果附近找到任何相关的 <li>
标签。
解决方案
要识别所需的元素,您需要为 visibility of element located()
引入 WebDriverWait,您可以使用以下任一解决方案:
使用CSS_SELECTOR
:
book = WebDriverWait(driver, 20).until(EC.element_to_be_clickable((By.CSS_SELECTOR, "div.sg-col-inner h5 a:first-child")))
使用XPATH
:
book = WebDriverWait(driver, 20).until(EC.element_to_be_clickable((By.XPATH, "//div[@class='sg-col-inner']//h5//following::a[1]/span")))
给定一个搜索词,我试图获取亚马逊上 Books 类别下的结果,并获取给定搜索词的每本书的详细信息。
我 运行 遇到一个问题,有时我的代码能够找到结果,有时却失败了。进一步检查后,我意识到这些项目有时会用 <li>
标签列出,有时会用 <div>
标签列出。
下面粘贴的是同一元素的元素和代码片段,以支持我的声明。
HTML 带有 <li>
标签:
<li id="result_0" data-asin="0128023074" class="s-result-item celwidget ">
HTML 带有 <div>
标签:
<div data-asin="0128023074" data-index="0" class="sg-col-20-of-24 s-result-item sg-col-0-of-12 sg-col-28-of-32 sg-col-16-of-20 sg-col sg-col-32-of-36 sg-col-12-of-16 sg-col-24-of-28" data-cel-widget="search_result_0"><div class="sg-col-inner">
我仍然是 Selenium 的新手,所以为了解决这个问题,我使用了以下代码片段,我很确定有更好的方法来处理这个问题。
try:
book = WebDriverWait(driver, 10).until(EC.visibility_of_element_located((By.ID, "result_0")))
book_detail(book, details)
except TimeoutException:
book = WebDriverWait(driver, 10).until(EC.visibility_of_element_located((By.XPATH, "//div[@data-index=\"0\" and @data-cel-widget=\"search_result_0\"]")))
book_detail_by_div(book, details)
谁能帮我理解为什么关联的标签会发生这样的变化,以及如何处理这样的情况?
关于你的第一个问题,为什么会这样,我不确定。我尝试了不同的 OS/Browser 和 window 大小,但无法重现 div
元素的大小写。
为了改进你的代码,我有一个建议,但它可能不是最适合你的解决方案,所以你可以试试。这将等待两种类型的元素中的任何一种一起可见,而不是等待 10 秒第一种然后第二种。
try:
book = WebDriverWait(driver, 10).until(EC.visibility_of_element_located((By.XPATH, '//*[(@id="result_0") or (@data-index="0" and @data-cel-widget="search_result_0")]')))
except TimeoutException:
print("Did not find search result")
else:
# So atleast one of the tag type is visible.
# Even if the attribute is not present then it will return None.
if book.get_attribute('id') == "result_0":
book_detail(book, details)
else:
book_detail_by_div(book, details)
我遵循了问题中提供的详细信息,并在 https://www.amazon.com
搜索文本 The Data and Analytics playbook 时显示了相同的元素。
所以,您对 <div>
标签的观察是正确的。但是我没有在搜索结果附近找到任何相关的 <li>
标签。
解决方案
要识别所需的元素,您需要为 visibility of element located()
引入 WebDriverWait,您可以使用以下任一解决方案:
使用
CSS_SELECTOR
:book = WebDriverWait(driver, 20).until(EC.element_to_be_clickable((By.CSS_SELECTOR, "div.sg-col-inner h5 a:first-child")))
使用
XPATH
:book = WebDriverWait(driver, 20).until(EC.element_to_be_clickable((By.XPATH, "//div[@class='sg-col-inner']//h5//following::a[1]/span")))