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 名称,您必须使用 XPath
或 css
选择器。
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/
- 尽可能避免多个内部循环。否则您的程序将非常缓慢且难以阅读。
我对网页抓取还很陌生,今天才学会。我正在尝试获取有关当前库存的数据,但出现了一个奇怪的错误。有什么帮助吗? 错误:
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 名称,您必须使用 XPath
或 css
选择器。
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/
- 尽可能避免多个内部循环。否则您的程序将非常缓慢且难以阅读。