如何使用Pyppeteer从Vanguard站点通过JS下载CSV/Excel文件
解决方案
核心问题根因
你当前代码无法触发下载主要有3个问题:
- 未配置Pyppeteer的下载规则:Pyppeteer默认不会自动处理下载请求,需要手动指定下载路径、开启下载权限
- 错误读取页面内容作为下载文件:点击下载按钮不会改变当前页面的HTML内容,你写入
csv_page{i}.csv的内容始终是当前页面的源码,和目标下载文件无关 - 固定延迟等待不稳定:固定2秒等待无法适配不同网络环境下的元素加载速度,容易出现点击未生效的问题
修改后可运行代码
import asyncio from pyppeteer import launch import os async def get_page(browser, url): page = await browser.newPage() await page.goto(url, timeout=30000) return page async def fetch(url): # 提前创建存储目录 wkg_dir = 'vanguard' os.makedirs(wkg_dir, exist_ok=True) # 启动浏览器,调试阶段可以先关闭headless看操作流程 browser = await launch(headless=False, options={'args': ['--no-sandbox']}) page = await get_page(browser, url) # 配置下载规则,指定文件保存路径 await page._client.send('Page.setDownloadBehavior', { 'behavior': 'allow', 'downloadPath': os.path.abspath(wkg_dir) }) # 监听下载事件,确认文件下载完成 async def on_download(download): save_path = await download.path() print(f"下载完成,文件路径:{save_path}") # 如果你需要自定义文件名可以在这里重命名 # new_name = os.path.join(wkg_dir, "holdings.xlsx") # os.rename(save_path, new_name) page.on('download', lambda d: asyncio.create_task(on_download(d))) # 等待「See count total holdings」链接可点击 await page.waitForXPath('//a[contains(., "See count total holdings")]', timeout=10000) accept = await page.xpath('//a[contains(., "See count total holdings")]') print(f'Found {len(accept)} "See count total holdings" links') if accept: # 避免元素遮挡导致点击失效,用JS执行点击 await page.evaluate('el => el.click()', accept[0]) else: print('DID NOT FIND THE LINK') await browser.close() return False # 等待「Export to CSV」链接加载完成 await page.waitForXPath('//a[contains(., "Export to CSV")]', timeout=10000) links = await page.xpath('//a[contains(., "Export to CSV")]') print(f'Found {len(links)} "Export to CSV" links') # 点击对应导出链接,这里第三个链接是全部持仓的导出按钮,你可以根据自己的需要选 target_link = links[2] await page.evaluate('el => el.click()', target_link) # 等待下载完成,可根据网络情况调整等待时间 await page.waitFor(5000) await browser.close() return True #---------- Main ------------ url = 'https://www.vanguard.com.au/personal/products/en/detail/8225/portfolio' asyncio.run(fetch(url))
注意事项
- 站点返回的实际是Excel格式文件,下载后可直接用
pandas.read_excel读取,不需要强制转CSV - 如果需要部署到服务器运行,把launch的
headless参数设为True即可,不影响下载逻辑 - 如果出现元素找不到的报错,可以适当调大
waitForXPath的timeout参数适配网络环境
内容的提问来源于stack exchange,提问作者InnocentBystander
相关产品推荐
相关产品推荐

