You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

网页爬取NBA数据导出CSV报错:IndexError列表索引越界

解决你的NBA数据爬取CSV导出报错问题

这个IndexError: list index out of range报错出现在table = soup.find_all('table')[1]这一行,本质原因是:你的代码尝试获取页面中第2个table(索引从0开始),但实际请求回来的页面里要么没有这么多table,要么请求被网站反爬机制拦截,返回了空页面/验证页面,导致找不到目标表格。

下面一步步帮你解决问题:

1. 先排查请求是否被拦截

首先在scrape_data函数里加几行调试代码,确认请求的有效性:

def scrape_data(url):
    response = requests.get(url, timeout=10)
    # 打印请求状态码(200代表成功,403/404就是有问题)
    print(f"请求状态码: {response.status_code}")
    soup = BeautifulSoup(response.content, 'html.parser')
    # 打印页面里的table总数
    print(f"页面table数量: {len(soup.find_all('table'))}")
    # 剩下的原有代码...

如果状态码不是200,或者table数量为0,那就是请求被网站反爬拦截了,需要模拟浏览器请求。

2. 添加请求头绕过反爬

CBS Sports会检测请求是否来自真实浏览器,我们给requests.get加上headers参数,模拟浏览器身份:

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, headers=headers, timeout=10)

3. 不要依赖索引定位表格

原代码用find_all('table')[1]靠索引选表格非常不稳定——网站结构一旦调整,索引就会失效。建议通过表格的class属性精准定位,比如观察页面源码,目标统计表格的class通常是TableBase-table,用以下代码替换原有的table定位逻辑:

# 精准定位统计表格,若class不对,可自己看页面源码调整
table = soup.find('table', class_='TableBase-table')
if not table:
    print("找不到目标表格,请检查页面结构或class名称")
    return

4. 修正表头和数据行的提取逻辑

原代码里的rows = table.select('tbody > tr')是错误的(>是HTML实体,应该直接写>),而且表头应该从thead标签里提取,而不是从tbody的行里取。

修改后的完整可运行代码

import csv
import requests
from bs4 import BeautifulSoup

def scrape_data(url):
    # 添加请求头模拟浏览器
    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, headers=headers, timeout=10)
    # 若请求失败直接抛出异常,方便排查
    response.raise_for_status()
    
    soup = BeautifulSoup(response.content, 'html.parser')
    # 精准定位目标统计表格
    table = soup.find('table', class_='TableBase-table')
    if not table:
        print("找不到目标表格,请检查页面结构或class名称")
        return
    
    # 从thead提取表头
    header = [th.text.strip() for th in table.find('thead').find_all('th')]
    # 从tbody提取所有数据行
    rows = table.find('tbody').find_all('tr')
    
    # 写入CSV,避免空行和乱码
    with open('statsoutput.csv', 'w', newline='', encoding='utf-8') as csv_file:
        writer = csv.writer(csv_file)
        writer.writerow(header)
        for row in rows:
            data = [td.text.strip() for td in row.find_all('td')]
            # 确保数据长度和表头一致,过滤无效行
            if len(data) == len(header):
                writer.writerow(data)

if __name__=="__main__":
    url = "https://www.cbssports.com/nba/stats/playersort/nba/year-2019-season-preseason-category-scoringpergame"
    scrape_data(url)

额外提示

如果还是找不到目标表格,打开浏览器F12开发者工具,查看页面源码里的统计表格的class/id,替换代码里的class_='TableBase-table'即可。

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

火山引擎 最新活动