Selenium截取LaTeX公式截图时放大后异常问题求助
问题:Selenium截取LaTeX公式截图的分辨率与白屏问题
低缩放比例下,脚本生成的截图正常但公式分辨率不足;高缩放时,手动检查元素保存的截图效果良好,但Selenium生成的截图质量很差,还偶尔出现大块白屏。
脚本说明
需先执行以下命令安装依赖,运行后会在当前目录创建temp文件夹并保存图片:
pip install selenium pyautogui webdriver-manager
原脚本代码
import os import time from selenium import webdriver from selenium.webdriver.common.by import By from selenium.webdriver.chrome.service import Service as ChromeService from webdriver_manager.chrome import ChromeDriverManager # from selenium.webdriver.chrome.options import Options import pyautogui dry_run = False # if False, don't save anything save_to_temp_folder = True # if True, save to temp folder instead of content/formulas (for previewing) # chrome_options = Options() # chrome_options.add_argument("--headless") driver = webdriver.Chrome(service=ChromeService(ChromeDriverManager().install())) driver.get('http://stemformulas.com/formulas') driver.implicitly_wait(10) def zoom_in(times=1): for i in range(times): pyautogui.hotkey('command', '+') # Find the list items within the specified <ul> element ul_element = driver.find_element(By.CSS_SELECTOR, 'ul.flex.flex-row.mt-8') list_items = ul_element.find_elements(By.TAG_NAME, 'li') # Count the number of list items. Subtract one for the next button. page_count = len(list_items) - 1 print(f"Found {page_count} pages of formulas") # increase zoom to 400% for higher quality screenshots # zoom_in(4) # driver.execute_script("document.body.style.zoom = '200%'") for i in range(1, page_count + 1): # iterate over pages print("Visiting page: ", i) # visit formulas page driver.get(f'http://stemformulas.com/formulas/page/{i}') # Find the section with class "grid-container mt-6" section = driver.find_element(By.CSS_SELECTOR, 'section.grid-container.mt-6') # Find all anchor elements within the section anchors = section.find_elements(By.TAG_NAME, 'a') num_anchors = len(anchors) print(f"Found ", num_anchors, " formula grid items") # Iterate over the formula grid items for i in range(num_anchors): # if I iterate over the anchors they become stale so refetch section, anchors every time section = driver.find_element(By.CSS_SELECTOR, 'section.grid-container.mt-6') anchors = section.find_elements(By.TAG_NAME, 'a') anchor = anchors[i] href = anchor.get_attribute('href') x_path = f"//*[@id=\"main-content\"]/section[2]/a[{i+1}]/div[1]" div = anchor.find_element(By.XPATH, x_path) div.location_once_scrolled_into_view # scroll into view # http://stemformulas.com/formulas/<folder_name>/ folder_name = href.split('/')[-2] output_image_path = os.path.join("content", "formulas", folder_name, "preview.png") if dry_run: print(f"Would have screenshot div {div} to {output_image_path}") elif save_to_temp_folder: if not os.path.exists("temp"): os.mkdir("temp") if not os.path.exists(os.path.join("temp", folder_name)): os.mkdir(os.path.join("temp", folder_name)) new_path = os.path.join("temp", folder_name, "preview.png") bits = div.screenshot_as_png with open(new_path, 'wb') as f: f.write(bits) print(f"Screenshot div {div} to {new_path}") time.sleep(1) else: bits = div.screenshot_as_png with open(output_image_path, 'wb') as f: f.write(bits) print(f"Screenshot div {div} to {output_image_path}") time.sleep(1) # if we don't sleep, elements become stale
已尝试的方案
- 使用
driver.execute_script("document.body.style.zoom = '400%'"),截图效果更差 - 使用headless模式,未解决问题
解决方案
1. 用Chrome设备像素比参数提升原生分辨率
使用--force-device-scale-factor参数设置全局缩放,这是Chrome原生的缩放方式,比JS修改或模拟快捷键更稳定,直接提升截图分辨率:
from selenium.webdriver.chrome.options import Options chrome_options = Options() # 设置4倍设备像素比(对应400%缩放) chrome_options.add_argument("--force-device-scale-factor=4") # 若使用headless模式,需配合窗口大小设置 chrome_options.add_argument("--headless=new") chrome_options.add_argument("--window-size=1920,1080") driver = webdriver.Chrome(service=ChromeService(ChromeDriverManager().install()), options=chrome_options)
2. 等待LaTeX公式完全渲染
implicitly_wait仅等待元素出现,不等待渲染完成。添加显式等待监听公式渲染状态(以KaTeX为例):
from selenium.webdriver.support.ui import WebDriverWait from selenium.webdriver.support import expected_conditions as EC # 滚动到元素后,等待公式渲染完成 div.location_once_scrolled_into_view WebDriverWait(driver, 5).until( EC.presence_of_element_located((By.CSS_SELECTOR, ".katex")) ) time.sleep(0.5) # 额外等待确保渲染稳定
3. 优化元素定位避免Stale异常
改用JS直接获取元素,减少重复定位的开销与StaleElement异常:
# 替换原循环内的元素定位逻辑 for idx in range(num_anchors): # 通过JS直接获取目标div div = driver.execute_script(f''' return document.querySelector('section.grid-container.mt-6').querySelectorAll('a')[{idx}].querySelector('div:first-child'); ''') div.location_once_scrolled_into_view # 等待元素可见与渲染 WebDriverWait(driver, 5).until(EC.visibility_of(div)) # 后续截图逻辑不变
4. 修复高缩放白屏问题
高缩放白屏多因元素未完全进入视口或渲染缓存问题,截图前强制重绘元素:
# 在截图前执行重绘 driver.execute_script("arguments[0].style.display = 'none'; arguments[0].style.display = 'block';", div)
内容的提问来源于stack exchange,提问作者kevinlinxc
相关产品推荐
相关产品推荐

