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

通过Python从Marketscreener获取ETF持仓数据并导出CSV

解决Marketscreener ETF持仓数据爬取(JS渲染页面)问题

你的判断没错——这个页面的持仓表格是通过JavaScript动态渲染的,requests只能抓取页面初始的静态HTML,不会执行页面中的JS代码,所以无法获取到动态加载的持仓数据。下面是用Playwright模拟浏览器渲染来解决这个问题的方案:

步骤1:安装依赖

先安装Playwright库和Chromium浏览器驱动:

pip install playwright
playwright install chromium

步骤2:完整爬取代码

from playwright.sync_api import sync_playwright
import csv

# ETF持仓页面URL
url = 'https://de.marketscreener.com/kurs/etf/DEKA-EURO-ISTOXX-EX-FIN-D-40509374/einzelwerte/'

with sync_playwright() as p:
    # 启动无头模式的Chromium(headless=True可改为False查看浏览器窗口)
    browser = p.chromium.launch(headless=True)
    page = browser.new_page(user_agent="Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/118.0.0.0 Safari/537.36")
    
    # 访问目标页面
    page.goto(url)
    
    # 等待持仓表格加载完成(超时时间10秒)
    page.wait_for_selector('table.BordCollapseYear2', timeout=10000)
    
    # 提取表格数据
    all_data = {}
    tables = page.locator('table.BordCollapseYear2').all()
    
    for table in tables:
        # 获取表格标题(前一个<b>标签的文本)
        table_name = table.locator('xpath=preceding-sibling::b[1]').text_content().strip()
        all_data[table_name] = []
        
        # 遍历表格行
        rows = table.locator('tr').all()
        for row in rows:
            # 提取每行的单元格文本,清理换行符
            cells = row.locator('td').all()
            row_data = [cell.text_content().strip().replace('\n', ' ') for cell in cells]
            if len(row_data) == 7:  # 筛选有效数据行
                all_data[table_name].append(row_data)
    
    # 关闭浏览器
    browser.close()

# 将数据保存为CSV文件
with open('etf_holdings.csv', 'w', newline='', encoding='utf-8') as csvfile:
    writer = csv.writer(csvfile, delimiter=',', quotechar='"', quoting=csv.QUOTE_MINIMAL)
    for table_name, rows in all_data.items():
        writer.writerow([table_name])
        writer.writerows(rows)

print("持仓数据已成功导出到etf_holdings.csv")

关键说明

  • Playwright模拟真实浏览器加载页面,自动执行所有JS代码,能获取到动态渲染的表格内容。
  • wait_for_selector方法确保等待表格元素加载完成后再提取数据,避免因页面未加载完全导致空数据。
  • 你原来的代码存在一个小问题:已经用带headers的requests.get获取了响应,但创建BeautifulSoup时又重新调用无headers的requests.get(url),这会增加被网站拦截的概率,但核心问题仍是JS渲染。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.08 06:42:46