Selenium动态爬取ESCO技能页面:展开按钮定位问题排查
ESCO技能页面动态展开爬取问题修复
问题说明
尝试爬取ESCO技能分类页面(动态加载),需要展开所有“+”按钮以获取完整数据,但全量展开时触发超时错误,怀疑是XPATH定位语句存在问题。
原代码核心问题
原XPATH存在语法错误:末尾多了一个多余的],导致无法正确定位元素:
# 错误XPATH,多了闭合的] expand_buttons = wait.until(EC.presence_of_all_elements_located((By.XPATH, "//div[@class='classification_item cont_change_right hierarchy_active']]//span[@class='api_hierarchy has-child-link']")))
此外,原逻辑一次性查找所有按钮并点击,容易因DOM频繁更新触发StaleElementReferenceException,且未判断按钮是否已经展开,重复点击会导致无效操作,进而触发超时。
修复方案
- 修正XPATH语法错误
- 每次仅定位当前可见且未展开的按钮(通过按钮文本判断)
- 分批点击并等待DOM加载稳定,避免一次性发送过多请求
- 优化循环逻辑,直到没有可展开按钮为止
修正后的完整代码
import time from selenium import webdriver from selenium.webdriver.common.by import By from selenium.webdriver.support.ui import WebDriverWait from selenium.webdriver.support import expected_conditions as EC from selenium.webdriver.chrome.service import Service from webdriver_manager.chrome import ChromeDriverManager from selenium.common.exceptions import StaleElementReferenceException, TimeoutException from bs4 import BeautifulSoup import json # 初始化浏览器 driver = webdriver.Chrome(service=Service(ChromeDriverManager().install())) driver.get("http://data.europa.eu/esco/skill/f8c676de-c871-424f-9a65-77059d07910a") wait = WebDriverWait(driver, 20) def click_expand_buttons(): while True: try: # 修正XPATH,定位所有未展开的"+"按钮(仅匹配当前可见的) expand_buttons = wait.until(EC.visibility_of_all_elements_located( (By.XPATH, "//div[@class='classification_item cont_change_right hierarchy_active']//span[@class='api_hierarchy has-child-link' and text()='+']") )) if not expand_buttons: break # 逐个点击,每次点击后等待DOM稳定 for idx, button in enumerate(expand_buttons): try: # 用JS点击避免元素遮挡问题 driver.execute_script("arguments[0].click();", button) # 等待当前节点加载完成,减少服务器请求压力 time.sleep(0.5) # 每点击5个按钮重新查找一次,避免元素过期 if idx % 5 == 0: break except StaleElementReferenceException: break except TimeoutException: # 超时说明没有更多可展开按钮 break # 执行展开操作 click_expand_buttons() # 提取页面数据 html_source = driver.page_source soup = BeautifulSoup(html_source, 'html.parser') skills = [] # 根据实际页面结构调整选择器 for skill_element in soup.find_all("div", class_="skill-class"): skill_name = skill_element.find("h2", class_="skill-name").text.strip() if skill_element.find("h2", class_="skill-name") else "无名称" skill_description = skill_element.find("p", class_="skill-description").text.strip() if skill_element.find("p", class_="skill-description") else "无描述" skills.append({"name": skill_name, "description": skill_description}) # 保存数据到JSON with open("/Users/federiconutarelli/Desktop/escodata/expanded_esco_skills_page.json", "w", encoding="utf-8") as json_file: json.dump(skills, json_file, indent=4, ensure_ascii=False) driver.quit()
关键优化点
- XPATH修正:移除多余的
],并增加text()='+'过滤已展开的按钮 - 分批点击:每点击5个按钮就重新查找,避免元素过期
- 等待策略:每次点击后短时间等待,降低服务器请求频率,避免超时
- 容错处理:增加对
TimeoutException的捕获,确保循环正常退出
内容的提问来源于stack exchange,提问作者Lusian
相关产品推荐
相关产品推荐

