Web scraping Selenium Error: "with AttributeError: 'list' object has no attribute 'find_element_by_class_name' "

Web scraping Selenium Error: "with AttributeError: 'list' object has no attribute 'find_element_by_class_name' "

我对网页抓取还很陌生,今天才学会。我正在尝试获取有关当前库存的数据,但出现了一个奇怪的错误。有什么帮助吗? 错误:

Traceback (most recent call last): File "c:\Users\Heage\Coding\Python\Selenium\WebScraping\Popular TV Shows\main.py", line 17, in company = companies.find_element_by_class_name("tv-data-table__row tv-data-table__stroke tv-screener-table__result-row") AttributeError: 'list' object has no attribute 'find_element_by_class_name'

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

PATH = "C:\Program Files (x86)\chromedriver.exe"
driver = webdriver.Chrome(PATH)
driver.get("https://www.tradingview.com/markets/stocks-usa/market-movers-active/")

try:
    main = WebDriverWait(driver, 10).until(
        EC.presence_of_element_located((By.ID, "js-screener-container")))
    companies = main.find_elements_by_class_name("tv-data-table__tbody")
    for company in companies:
        company = companies.find_element_by_class_name("tv-data-table__row tv-data-table__stroke tv-screener-table__result-row")
        for companyInfo in company:
            companyInfo = company.find_element_by_class_name("tv-data-table__cell apply-common-tooltip tv-screener-table__cell tv-screener-table__cell--left tv-screener-table__cell--big tv-screener-table__cell--with-marker")
            for companyInfoMore in companyInfo:
                companyInfoMore = companyInfo.find_element_by_class_name("tv-screener-table__symbol-container ")
                for companyTitle in companyInfoMore:
                    companyTitle = companyInfoMore.find_element_by_class_name("tv-screener__symbol apply-common-tooltip")
                    print(companyTitle)
            for companyChangePercent in companyInfo:
                companyChangePercent = companyInfo.find_element_by_class_name("tv-data-table__cell tv-screener-table__cell tv-screener-table__cell--up tv-screener-table__cell--big tv-screener-table__cell--with-marker")
                print(companyChangePercent)

finally:
    driver.quit()
company = companies.find_element_by_class_name("tv-data-table__row tv-data-table__stroke tv-screener-table__result-row")

看看这一行。 companies(注意是复数形式)是从 find_elements_by_class_name 定义的,其 return 值为列表。因此,公司是一个列表,它没有这样的属性。

猜猜可以是这样的

company = company.find_element_by_class_name("tv-data-table__row tv-data-table__stroke tv-screener-table__result-row")

这为公司分配了一个新元素。它有方法 - find_element_by_class_name

Nikita 的回答解释了为什么您的代码会产生此错误。 但是目前的实现是非常错误的。

1 您使用了多个 for 循环。你不需要这个

2 您将 find_element_by_class_name 用于多个 class 名称。但这不受支持。对于多个 class 名称,您必须使用 XPathcss 选择器。

3 您正在这样等待:main = WebDriverWait(driver, 10).until( EC.presence_of_element_located((By.ID, "js-screener-container"))) 但它不太可能等待 table 内容。

4 您正在等待元素出现,但等到它们可见更可靠

回答您的主要问题: 'list' object has no attribute 'find_element_by_class_name' 意味着您正在从列表中调用 find_element_by_class_name 方法,而列表中没有它。你应该这样使用它:

driver. find_element_by_class_name("some_class")

我已经开始写你的代码了,所以你会更容易理解代码的真正样子。

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

driver = webdriver.Chrome(executable_path='/snap/bin/chromium.chromedriver')
driver.get("https://www.tradingview.com/markets/stocks-usa/market-movers-active/")


main = WebDriverWait(driver, 10).until(
    EC.visibility_of_all_elements_located((By.CSS_SELECTOR, ".tv-data-table__tbody .tv-data-table__row.tv-data-table__stroke.tv-screener-table__result-row")))
companies = driver.find_elements_by_css_selector(".tv-data-table__tbody .tv-data-table__row.tv-data-table__stroke.tv-screener-table__result-row")
result = []
for company in companies:
    name_short = company.find_element_by_css_selector(".tv-screener__symbol.apply-common-tooltip").text
    name_long = company.find_element_by_css_selector(".tv-screener__description").text
    last = company.find_element_by_css_selector(".tv-data-table__cell.tv-screener-table__cell.tv-screener-table__cell--big.tv-screener-table__cell--with-marker:nth-of-type(2)>span").text
    result.append([name_short, name_long, last])
for p in result:
    print(p, sep='\n')

输出的前 5 行:

['GERN', 'GERON CORPORATION', '1.83']
['AMC', 'AMC ENTERTAINMENT HOLDINGS, INC.', '59.26']
['XLF', 'SPDR SELECT SECTOR FUND - FINANCIAL ETF', '35.23']
['WISH', 'CONTEXTLOGIC INC.', '11.40']
['SNDL', 'SUNDIAL GROWERS INC.', '0.9230']

一些提示:

  • 学习定位器,特别是 XPATH 和 CSS
  • 了解如何使用列表
  • 完成本教程以更好地了解 Selenium https://selenium-python.readthedocs.io/
  • 尽可能避免多个内部循环。否则您的程序将非常缓慢且难以阅读。