使用Selenium爬取网站图片遇JavascriptException错误,求排查解决
问题分析与解决
错误原因
你遇到的Cannot read properties of undefined (reading 'click')错误,本质是执行JS代码时,document.getElementsByClassName('accordion-toggle')[0]返回了undefined——也就是页面上找不到class为accordion-toggle的第一个元素,自然没法调用click()方法。核心问题出在这几点:
- 固定sleep不可靠:用
sleep(10)等待页面加载,但网络波动、页面渲染速度差异会导致元素还没加载完成就执行点击代码,或者元素早就加载了还在浪费时间等待。 - 无检查直接操作:不管元素是否存在就强行调用
click(),遇到没有这个元素的页面直接报错中断。 - JS操作不是最优解:直接用JS定位元素不如用Selenium原生定位方法,后者更容易结合等待机制和异常处理。
正确处理方式
- 用显式等待替代固定sleep:Selenium的
WebDriverWait可以等待元素满足可点击/存在的条件,超时才抛出异常,比固定时间等待更灵活可靠。 - 优先用Selenium原生定位:用
find_element系列方法定位目标元素,替代直接执行JS,更符合爬取的最佳实践。 - 增加异常捕获:处理元素不存在的场景,跳过点击步骤,不影响后续爬取图片的逻辑。
- 验证页面结构:确认目标元素的class是否还是
accordion-toggle,若网站更新了结构,需要调整定位方式(比如用XPath、其他属性定位)。
修改后的代码示例
from selenium.webdriver.support.ui import WebDriverWait from selenium.webdriver.support import expected_conditions as EC from selenium.common.exceptions import TimeoutException, NoSuchElementException for idx, row in tqdm(df.iterrows(), total=df.shape[0]): imgs = [] try: driver.get(row['listing_url']) # 显式等待目标元素可点击,超时时间10秒 try: accordion_toggle = WebDriverWait(driver, 10).until( EC.element_to_be_clickable((By.CLASS_NAME, 'accordion-toggle')) ) accordion_toggle.click() except (TimeoutException, NoSuchElementException): # 元素找不到或超时,跳过点击,继续后续逻辑 print(f"页面 {row['listing_url']} 未找到可点击的accordion-toggle元素") scroll_down(driver) # 等待图片元素加载完成 WebDriverWait(driver, 10).until( EC.presence_of_all_elements_located((By.XPATH, '//img[@class="i1o0kbi8 i1mla2as i1cqnm0r dir dir-ltr"]')) ) imgs = driver.find_elements(By.XPATH, '//img[@class="i1o0kbi8 i1mla2as i1cqnm0r dir dir-ltr"]') imgs = list(set([img.get_attribute('src') for img in imgs])) finally: os.makedirs('images', exist_ok=True) with open(f'images/{row["id"]}_{row["host_id"]}.json', 'w') as f: json.dump(imgs, f)
补充说明
- 显式等待会在元素满足条件时立即执行,不用等满固定时间,爬取效率更高。
- 捕获异常后程序不会中断循环,能保证批量爬取的连续性。
- 如果仍找不到
accordion-toggle元素,需要打开目标页面的开发者工具,重新确认元素的定位信息是否正确。
内容的提问来源于stack exchange,提问作者rcd
相关产品推荐
相关产品推荐

