You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何指定抓取NBA数据页第5个表格?遇IndexError求助

解决NBA Stats页面表格抓取的问题

Hey, let's break down the issues you're facing and fix them step by step:

Why You're Getting the IndexError

The NBA Stats page loads most of its table data dynamically using JavaScript. When you use urlopen to fetch the page, you're only getting the initial static HTML source—none of the actual table rows are present yet. That's why soup.findAll('tr') returns an empty list, and trying to access [1] throws an index out of range error.

NBA Stats serves its data via backend APIs, which is way more reliable than scraping HTML. You can directly request the JSON data and convert it to a DataFrame without dealing with parsing messy HTML.

Here's how to get the exact data you're after (player ID 2544, 2017-18 Playoffs, last 6 games):

import pandas as pd
import requests

# API endpoint for shot chart details
url = "https://stats.nba.com/stats/shotchartdetail"

# Request parameters matching your original URL
params = {
    "PlayerID": 2544,
    "Season": "2017-18",
    "SeasonType": "Playoffs",
    "LastNGames": 6,
    "LeagueID": "00",
    "ContextMeasure": "FGM",
    "TeamID": 0,
    "OpponentTeamID": 0,
    "PerMode": "PerGame"
}

# Mimic a browser request to avoid being blocked
headers = {
    "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/114.0.0.0 Safari/537.36"
}

response = requests.get(url, params=params, headers=headers)
data = response.json()

# Extract headers and rows, then create DataFrame
column_headers = data["resultSets"][0]["headers"]
data_rows = data["resultSets"][0]["rowSet"]
df = pd.DataFrame(data_rows, columns=column_headers)

print(df.head())

Solution 2: Scrape Dynamic Content with Selenium

If you prefer to stick with scraping the page directly, you'll need a tool that can render JavaScript. Selenium simulates a real browser, so it waits for the page to fully load before you extract the HTML.

from selenium import webdriver
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
from selenium.webdriver.common.by import By
from bs4 import BeautifulSoup
import pandas as pd

url = 'http://stats.nba.com/player/2544/shots-dash/?Season=2017-18&SeasonType=Playoffs&LastNGames=6&sort=FGM&dir=1'

# Initialize Chrome driver (download chromedriver matching your Chrome version first)
driver = webdriver.Chrome()
driver.get(url)

# Wait up to 10 seconds for tables to load
try:
    WebDriverWait(driver, 10).until(
        EC.presence_of_element_located((By.TAG_NAME, "table"))
    )
except TimeoutError:
    print("Page took too long to load")
    driver.quit()
    exit()

# Get the fully rendered page source
html = driver.page_source
driver.quit()

soup = BeautifulSoup(html, "html.parser")

# Target the 5th table (index 4, since Python uses 0-based indexing)
tables = soup.find_all('table')
if len(tables) >= 5:
    target_table = tables[4]
    
    # Extract column headers (skip the first row if it's a header wrapper)
    column_headers = [th.get_text(strip=True) for th in target_table.find_all('tr')[1].find_all('th')]
    
    # Extract data rows (skip the first two header rows)
    data_rows = target_table.find_all('tr')[2:]
    table_data = []
    for row in data_rows:
        row_data = [td.get_text(strip=True) for td in row.find_all('td')]
        table_data.append(row_data)
    
    # Convert to DataFrame
    df = pd.DataFrame(table_data, columns=column_headers)
    print(df.head())
else:
    print("Couldn't find the 5th table on the page")

Quick Tip for Targeting Tables

When all tables use the same <table> tag, you can grab all tables with soup.find_all('table') and use indexing to pick the one you want. Always check the length of the tables list first to avoid index errors—like we did with if len(tables) >=5 in the code above.

内容的提问来源于stack exchange,提问作者dejsdukes

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.29 07:15:49