修复Selenium ActionChains循环分页爬取仅获对应序号内容的问题
问题修复方案
你的核心问题是循环逻辑错误:当前代码把「单页爬取单个问题」和「翻页」放在同一个循环里,导致第i次循环只爬取当前页的第i个问题,然后直接翻页,自然每页只拿到1个内容。
修复步骤:
- 拆分循环层级:外层循环控制翻页次数,内层循环负责爬取当前页的全部15个问题。
- 重新定位元素:每次进入新页面后,必须重新获取所有
card-topic元素,避免页面刷新导致的「元素过时」错误。 - 替换硬等待:用
WebDriverWait替代time.sleep,提升稳定性和效率。 - 增加翻页判断:检查「Selanjutnya」按钮是否可点击,避免最后一页无下一页时抛出异常。
修改后的完整代码:
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.common.action_chains import ActionChains from selenium.common.exceptions import NoSuchElementException, TimeoutException question_data = [] max_pages = 5 # 按需设置要爬取的总页数,或者改成循环直到无下一页 def expand_shadow_element(element): return driver.execute_script('return arguments[0].shadowRoot', element) for page in range(max_pages): try: # 等待当前页的所有card-topic加载完成 WebDriverWait(driver, 10).until( EC.presence_of_all_elements_located((By.CSS_SELECTOR, '#topic-list card-topic')) ) # 获取当前页所有问题元素 topic_cards = driver.find_elements(By.CSS_SELECTOR, '#topic-list card-topic') # 内层循环爬取当前页的15个问题 for card in topic_cards: shadow_root = expand_shadow_element(card) # 点击进入问题详情页 shadow_root.find_element(By.CSS_SELECTOR, 'a').click() # 等待详情页的user-topic加载完成 WebDriverWait(driver, 10).until( EC.presence_of_element_located((By.CSS_SELECTOR, 'user-topic')) ) qt = driver.find_element(By.CSS_SELECTOR, 'user-topic') qt_root = qt.shadow_root qt_ele = qt_root.find_element(By.CSS_SELECTOR, 'p') question_data.append(qt_ele.text) # 返回列表页 driver.back() # 等待列表页重新加载完成 WebDriverWait(driver, 10).until( EC.presence_of_all_elements_located((By.CSS_SELECTOR, '#topic-list card-topic')) ) # 执行翻页操作 paginate = driver.find_element(By.CSS_SELECTOR, 'paginate-button') paginate_root = expand_shadow_element(paginate) try: paginate2 = paginate_root.find_element(By.LINK_TEXT, 'Selanjutnya') # 检查按钮是否可点击 if paginate2.is_enabled(): actions = ActionChains(driver) actions.move_to_element(paginate2).click().perform() # 等待下一页加载完成 WebDriverWait(driver, 10).until( EC.staleness_of(topic_cards[0]) # 等待旧页面元素失效,说明新页面已加载 ) else: break # 按钮不可点击,结束循环 except NoSuchElementException: break # 无下一页按钮,结束循环 except TimeoutException: print(f"第{page+1}页加载超时,跳过") continue print(f"共爬取{len(question_data)}个问题")
关键说明:
- 双层循环:外层控制翻页,内层遍历当前页所有问题,确保每页15个都能被爬取。
- 显式等待:用
WebDriverWait等待元素加载,比time.sleep更灵活,能适应不同网络速度。 - 元素重新定位:每次回到列表页和进入新页面后,都重新获取元素,避免
StaleElementReferenceException。 - 翻页边界处理:判断下一页按钮是否存在、是否可用,防止最后一页报错。
内容的提问来源于stack exchange,提问作者abbym
相关产品推荐
相关产品推荐

