如何使用Python爬取网站中JavaScript加载到canvas内的图片
爬取musictheory.net canvas渲染内容的解决方案
问题核心
目标页面的知识点示意图都是通过JS实时渲染到canvas标签内的,没有可直接抓取的img标签资源,不需要逆向解析JS渲染逻辑,直接调用浏览器自带的canvas导出API即可获取渲染完成的图片。
现有代码问题修正
你当前的代码存在方向错误:你遍历的是script标签,而canvas是独立的DOM元素,不需要从脚本内容中提取。
可直接运行的实现代码
from helium import * import time import base64 url = 'https://www.musictheory.net/lessons/10' # 调试阶段建议先关闭headless模式,确认逻辑正常后再开启 browser = start_chrome(url, headless=False) # 等待页面初始加载完成 time.sleep(3) # 定位所有带role="button"属性的知识点触发按钮 lesson_buttons = find_all(S('div[role="button"]')) for idx, btn in enumerate(lesson_buttons): # 触发按钮点击事件,加载对应知识点的示意图 click(btn) # 等待canvas渲染完成,可根据网络情况调整延迟时长 time.sleep(1) # 执行浏览器原生JS,将当前canvas内容导出为PNG格式的base64编码 canvas_base64 = browser.execute_script('return document.querySelector("canvas").toDataURL("image/png")') # 处理base64编码,提取图片二进制内容 img_binary = base64.b64decode(canvas_base64.split(',')[1]) # 保存图片到本地 with open(f'musictheory_lesson10_{idx}.png', 'wb') as f: f.write(img_binary) # 任务完成后关闭浏览器 kill_browser()
实现要点
- 依赖helium控制浏览器模拟用户点击行为,触发对应知识点的canvas渲染
- 直接调用浏览器原生
HTMLCanvasElement.toDataURL()API导出已渲染内容,无需逆向JS逻辑 - 导出的base64内容解码后即可得到标准图片文件,支持PNG、JPEG等常用格式
注意事项
- 如果导出的图片存在空白,可适当延长点击后的等待时长,确保canvas渲染完成
- 若需要更高清的图片,可以先通过JS调整canvas的宽高属性后再执行导出
- 批量爬取时可添加随机延迟,避免触发网站反爬机制
内容的提问来源于stack exchange,提问作者Raphael Tunji
相关产品推荐
相关产品推荐

