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

使用Python+BeautifulSoup爬取Transfermarkt球员数据分页问题

问题原因分析
  • 索引越界报错:当前页面仅返回25条球员数据,你通过find_all查询得到的Players、Values等列表长度最大为25,当循环索引超过24(列表从0开始计数)时自然会触发越界错误。
  • 点击翻页URL不变:Transfermarkt的翻页参数为URL末尾附加的page参数,肉眼看到URL无变化是浏览器前端渲染隐藏了参数,实际第二页请求地址就是原URL末尾拼接&page=2,第三页拼接&page=3,以此类推即可。
实现全量爬取的方案

1. 先修复单页提取逻辑的问题

你现有代码存在两个隐藏问题:

  • 硬编码range(0,25),部分页面可能数据不足25条,容易触发越界
  • 缺少Values_pre的提取逻辑,需要对应补上对应节点的查询代码

2. 增加翻页循环控制

外层加页码循环,直到某一页查询不到球员数据时自动停止即可,完整可运行代码参考如下:

import requests
from bs4 import BeautifulSoup
import pandas as pd
import time
import random

headers = {'User-Agent': 
           'Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36'}

base_url = "https://www.transfermarkt.co.uk/transfers/transferrekorde/statistik?saison_id=alle&land_id=0&ausrichtung=&spielerposition_id=&altersklasse=&leihe=&w_s=&plus=1"

# 存储全量数据的列表
all_data = []
page_num = 1

while True:
    # 拼接翻页地址
    current_url = f"{base_url}&page={page_num}"
    response = requests.get(current_url, headers=headers)
    # 请求失败就重试2次,还是失败就终止
    if response.status_code != 200:
        for _ in range(2):
            time.sleep(2)
            response = requests.get(current_url, headers=headers)
            if response.status_code == 200:
                break
        else:
            print(f"第{page_num}页请求失败,终止爬取")
            break
    
    soup = BeautifulSoup(response.content, 'html.parser')
    Players = soup.find_all("a", {"class": "spielprofil_tooltip"})
    # 没有球员数据说明爬完所有页了,终止循环
    if not Players:
        print(f"所有页面爬取完成,共爬取{page_num-1}页")
        break
    
    Values = soup.find_all("td", {"class": "rechts hauptlink"})
    # 注意这里补你自己的Values_pre提取逻辑,替换成对应节点的选择器
    Values_pre = soup.find_all("替换为你对应节点的class或标签规则")
    Age = soup.find_all("td", {"class": "zentriert"})
    
    # 单页循环用列表最小长度作为上限,避免越界
    max_idx = min(len(Players), len(Values), len(Values_pre)//2, len(Age)//5)
    for i in range(max_idx):
        try:
            item = {
                "Players": Players[i].text,
                "Value_post": Values[i].text,
                "value_pre": Values_pre[2*i].text,
                "rank": Age[(5*i)].text,
                "age": Age[1 + (5*i)].text,
                "season": Age[2 + (5*i)].text,
                "missing": Age[3 + (5*i)].text,
                "team": Age[4 + (5*i)].text
            }
            all_data.append(item)
        except Exception as e:
            print(f"第{page_num}页第{i}条数据提取失败:{e}")
            continue
    
    print(f"第{page_num}页爬取完成,累计{len(all_data)}条数据")
    page_num += 1
    # 加1-3秒随机延时,避免被封IP
    time.sleep(random.uniform(1, 3))

# 转成DataFrame
df = pd.DataFrame(all_data)
print(df.head())
注意事项
  • 不要爬取频率过高,必须加延时,Transfermarkt反爬策略比较严格,高频请求容易被封IP
  • 如果需要爬取大量数据,建议搭配代理IP池使用
  • 部分特殊球员的字段可能存在缺失,可以根据自己的需求调整异常捕获的处理逻辑

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.27 16:06:09