Playwright无法加载本地资源,截图为空问题求助
问题原因及解决方法
核心问题
截图空白主要是两个原因叠加导致:
- 使用
page.set_content加载的页面处于about:blank源,Chromium对该源访问本地文件的权限限制,即使加了启动参数也无法完全绕过,尤其是在headless模式下。 - 未等待图片加载完成就执行截图,导致图片还未渲染就被捕获。
具体解决方案
方案1:改用本地HTML文件加载(推荐)
把HTML代码保存成本地文件(比如/home/user/test.html),修改screenshot方法,用page.goto加载file协议路径,而非set_content:
async def screenshot_from_file(self, file_path: str, clip: dict) -> bytes: if not self.is_inital: await self.inital_browser() page = await self.browser.new_page() # Linux/macOS下file协议格式为file:///绝对路径(三个斜杠) await page.goto(f"file://{file_path}") # 等待图片加载完成并可见 await page.wait_for_selector("#pic", state="visible") buffer = await page.screenshot(clip=clip) await page.close() return buffer
调用时传入本地HTML文件的绝对路径即可,此时页面处于file协议源,加载本地图片不会有权限问题。
方案2:将图片转为Base64嵌入HTML
如果不想保存本地HTML文件,可以把图片编码成Base64直接嵌入img标签,彻底绕开本地文件访问限制:
import base64 def image_to_base64(img_path: str) -> str: with open(img_path, "rb") as f: return base64.b64encode(f.read()).decode("utf-8") # 生成带Base64图片的HTML img_base64 = image_to_base64("/home/user/picture.png") html = f'''<!DOCTYPE html> <html> <head> <meta charset="utf_8"> <body> <img id="pic" src="data:image/png;base64,{img_base64}"> </body> </html>'''
再把这个HTML传入原有的screenshot方法,同时添加等待图片加载的逻辑:
async def screenshot(self, html, clip: dict) -> bytes: if not self.is_inital: await self.inital_browser() page = await self.browser.new_page() await page.set_content(html) # 等待图片可见 await page.wait_for_selector("#pic", state="visible") buffer = await page.screenshot(clip=clip) await page.close() return buffer
方案3:修正file://路径格式并等待加载
如果坚持用set_content,需要确保img的src是正确的file协议格式(三个斜杠),并等待图片加载:
修改后的HTML:
<!DOCTYPE html> <html> <head> <meta charset="utf_8"> <body> <img id="pic" src="file:///home/user/picture.png"> </body> </html>
然后在screenshot方法中添加等待逻辑(同方案2的wait_for_selector),同时调整Chromium启动参数,移除已废弃的--allow-file-access:
self.browser = await self.playwright.chromium.launch( headless=True, args=[ "--no-sandbox", "--disable-web-security", "--allow-file-access-from-files" ] )
内容的提问来源于stack exchange,提问作者Kulo
相关产品推荐
相关产品推荐

