1
resposta

Problema para fazer scraping no site da NBA

import requests
import pandas as pd
from bs4 import BeautifulSoup
from selenium import webdriver
from selenium.webdriver.firefox.options import Options
import json

url = "https://stats.nba.com/players/traditional/?PerMode=Totals&Season=2019-20&SeasonType=Regular%20Season&sort=PLAYER_NAME&dir=-1"

option = Options()
option.headless = True
driver = webdriver.Firefox()
driver.get(url)

driver.find_element_by_xpath(f"//div[@class='nba-stat-table']//table//thead//tr//th[@data-field='PTS']").click()
element = driver.find_element_by_xpath("//div[@class='nba-stat-table']//table")
html_content = element.get_attribute('outerHTML')

soup = BeautifulSoup(html_content, 'html.parser')
table = soup.find(name='table')
print(table)

driver.quit()

Esse é o código feito até o momento e estou tendo alguns problemas:

  • find_element_by_xpath aparece riscado e na aba de erros sugere: find_element_by_* commands are deprecated. Please use find_element() instead
  • E quando clico em run aparece o seguinte erro:
C:\Users\mfsra_m8bvnzn\PycharmProjects\ScraperMelee\venv\Scripts\python.exe C:/Users/mfsra_m8bvnzn/PycharmProjects/ScraperMelee/main.py
C:\Users\mfsra_m8bvnzn\PycharmProjects\ScraperMelee\main.py:15: DeprecationWarning: find_element_by_* commands are deprecated. Please use find_element() instead
  driver.find_element_by_xpath(f"//div[@class='nba-stat-table']//table//thead//tr//th[@data-field='PTS']").click()
Traceback (most recent call last):
  File "C:\Users\mfsra_m8bvnzn\PycharmProjects\ScraperMelee\main.py", line 15, in <module>
    driver.find_element_by_xpath(f"//div[@class='nba-stat-table']//table//thead//tr//th[@data-field='PTS']").click()
  File "C:\Users\mfsra_m8bvnzn\PycharmProjects\ScraperMelee\venv\lib\site-packages\selenium\webdriver\remote\webdriver.py", line 514, in find_element_by_xpath
    return self.find_element(by=By.XPATH, value=xpath)
  File "C:\Users\mfsra_m8bvnzn\PycharmProjects\ScraperMelee\venv\lib\site-packages\selenium\webdriver\remote\webdriver.py", line 1238, in find_element
    return self.execute(Command.FIND_ELEMENT, {
  File "C:\Users\mfsra_m8bvnzn\PycharmProjects\ScraperMelee\venv\lib\site-packages\selenium\webdriver\remote\webdriver.py", line 418, in execute
    self.error_handler.check_response(response)
  File "C:\Users\mfsra_m8bvnzn\PycharmProjects\ScraperMelee\venv\lib\site-packages\selenium\webdriver\remote\errorhandler.py", line 243, in check_response
    raise exception_class(message, screen, stacktrace)
selenium.common.exceptions.NoSuchElementException: Message: Unable to locate element: //div[@class='nba-stat-table']//table//thead//tr//th[@data-field='PTS']
Stacktrace:
WebDriverError@chrome://remote/content/shared/webdriver/Errors.jsm:181:5
NoSuchElementError@chrome://remote/content/shared/webdriver/Errors.jsm:393:5
element.find/</<@chrome://remote/content/marionette/element.js:299:16

Agradeço antecipadamente se acharem uma solução pra esse problema.

1 resposta

Olá Marcos, tudo bem? Espero que sim!

Desculpe pela demora em retornar.

Em relação ao aviso find_element_by_* commands are deprecated. Please use find_element() instead, essas funções estão depreciadas em versões mais novas da biblioteca e você pode fazer a troca delas pela função find_element() passando o parâmetro By.XPATH. É necessário fazer um import no início do código: from selenium.webdriver.common.by import By.

Para mais informações, veja o link de uma discussão no StackOverflow: find_element_by_* commands are deprecated in selenium. O link está em inglês, mas você pode utilizar a ferramenta do google translate para traduzir a página, caso necessário.

Em relação ao código em si, o problema pode estar ocorrendo pelo fato de ao clicar no botão PTS para mudar a ordenação, a página é atualizada e não dá tempo suficiente para conseguir localizar o elemento na próxima linha de código. Você pode adicionar um tempo de espera entre as linhas de código para o problema ser evitado. Você pode adicionar um tempo de espera através do comando time.sleep(), sendo necessário importar a biblioteca time com o código import time

Além disso, tentei rodar por aqui e aparecia um botão de aceitar os cookies e foi necessário fazer um passo a mais para clicar nesse botão. Adicionei uma parada de 2 segundos entre cada linha de código enquanto estava atualizando a página. O código final ficou o seguinte:

import requests
import pandas as pd
from bs4 import BeautifulSoup
from selenium import webdriver
from selenium.webdriver.firefox.options import Options
import json
import time

url = "https://stats.nba.com/players/traditional/?PerMode=Totals&Season=2019-20&SeasonType=Regular%20Season&sort=PLAYER_NAME&dir=-1"

option = Options()
option.headless = True
driver = webdriver.Firefox()
driver.get(url)
time.sleep(2)
driver.find_element_by_id("onetrust-accept-btn-handler").click()
time.sleep(2)
driver.find_element_by_xpath(f"//div[@class='nba-stat-table']//table//thead//tr//th[@data-field='PTS']").click()
time.sleep(2)
element = driver.find_element_by_xpath("//div[@class='nba-stat-table']//table")
html_content = element.get_attribute('outerHTML')

soup = BeautifulSoup(html_content, 'html.parser')
table = soup.find(name='table')
print(table)

driver.quit()

Espero que tenha tirado sua dúvida.

Estou à disposição. Bons estudos!