如何使用硒元素忽略列表中的某些项目



我正试着刮出这样的东西。

<ul>
<li> apple <b>price:2.8</b> </li>
<li> orange </li>
<li> banana <b>price:4.3</b> </li>
<li> peach <b>price:2.3</b> </li>
</ul>

有些商品没有价格,也不确定会是哪一种。我需要知道名字和价格。如果它没有价格,那么忽略这条线。

这是我的代码:

name_list = driver.find_elements(By.TAG_NAME, "li")
price_list = driver.find_elements(By.TAG_NAME, "b")
for n in name_list:
name = name_list[n]
price = price_list[n]

错误消息是";IndexError:列表索引超出范围";因为名称和价格的长度不同。

有什么办法可以解决的吗?

不要创建两个单独的列表。您可以获取所有<li/>元素,对结果进行迭代,并对每个元素调用find_elements(…(来查询其子元素。

像这样的东西可以工作:

name_list = driver.find_elements_by_tag_name("li")
for n in name_list:
child = n.find_elements_by_tag_name("b")
// check if it is present, then do stuff

有关详细信息,请查看Selenium文档。

(你也不正确地使用了for…in,它在元素上迭代,而不是在索引上(

这应该能在中工作

fruits = driver.find_elements_by_css_selector('li,b')          # finds both elements
for item in fruits:                                            # iterate through list
fruit = item.text                                          # the elements text
if fruit.find('price:') > 0:                               # consider only those with 'prices'
price =fruit[fruit.find(':')+1:]                       # just the price value w/o the word 'price'
name =  fruit[0:fruit.find('price:')]                  # just the name of the fruit
print (f'{name}price: {price}')                        # You may put it into a dictionary instead of printing.

apple price: 2.8
banana price: 4.3
peach price: 2.3
Process finished with exit code 0

下面是一个完整的工作示例,展示了如何获取价格数据:

from selenium import webdriver
from selenium.webdriver.common.keys import Keys
from selenium.webdriver.common.by import By
from selenium.common.exceptions import NoSuchElementException
driver = webdriver.Firefox()
driver.get("file:///Users/brian/pysel/test_data.html")
name_list = driver.find_elements(By.TAG_NAME, "li")
price_list = driver.find_elements(By.TAG_NAME, "b")
namePriceData = {}
for i, ele in enumerate(name_list):
name = name_list[i]
try:
price = ele.find_element(By.TAG_NAME, "b")
except NoSuchElementException as err:
namePriceData[name.text] = ""
continue

namePriceData[name.text[:len(name.text) - len(price.text)]] = price.text
print(namePriceData)
driver.close()

我们通过在name_list中的每个li元素上调用find_element来实现这一点。这允许我们获得元素的子元素。

这个测试数据有点奇怪,因为我们必须获取父元素的文本,然后使用字符串长度将子文本切片。若您遇到具有不同节点结构的真实数据,则在页面上查找这些元素的策略将发生变化。

此外,请注意:

原始代码返回了一个错误,因为它使用了n作为试图索引到元素列表中的键。

---------------------------------------------------------------------------
TypeError                                 Traceback (most recent call last)
/var/folders/ct/tm9p5wz92dz4l60w9l503f780000gn/T/ipykernel_27037/104717083.py in <module>
6 
7 for n in name_list:
----> 8     name = name_list[n]
9     price = price_list[n]
TypeError: list indices must be integers or slices, not WebElement

如果您想以这种方式访问元素,我们需要使用索引而不是实际值进行迭代。在Python中,我们使用enumerate来完成此操作。

由于索引越界错误,使用一个数组的长度索引到另一个数组是错误的,但一旦我们达到一个价格为空的值,它实际上将被分配下一个真正有价格的项目的价格,并且从那时起分配的值是不正确的,直到我们达到索引越界错误。

相反,最好使用实际元素而不是索引进行迭代:

from selenium import webdriver
from selenium.webdriver.common.keys import Keys
from selenium.webdriver.common.by import By
from selenium.common.exceptions import NoSuchElementException
driver = webdriver.Firefox()
driver.get("file:///Users/brian/pysel/test_data.html")
name_list = driver.find_elements(By.TAG_NAME, "li")
price_list = driver.find_elements(By.TAG_NAME, "b")
namePriceData = {}
for ele in name_list:
try:
price = ele.find_element(By.TAG_NAME, "b")
except NoSuchElementException as err:
namePriceData[ele.text] = ""
continue

namePriceData[ele.text[:len(ele.text) - len(price.text)]] = price.text
print(namePriceData)
driver.close()

最新更新