Python for循环传值异常 Selenium爬虫触发NoSuchElementException报错
Selenium爬取时for循环中断、NoSuchElementException问题根因
核心问题本质
你遇到的循环中断、元素定位失败不是字符串格式化本身的bug,是代码逻辑存在多处明确错误,导致循环未按预期执行、翻页逻辑提前触发,最终元素查找失败。
代码中存在的明确Bug
- 滚动逻辑未实际生效
你写的滚动代码tartget_element.location_once_scrolled_into_view是WebElement的属性,不是可执行的方法,必须在末尾加括号写成tartget_element.location_once_scrolled_into_view()才会真正触发滚动。因为没有实际滚动,懒加载的列表不会渲染第11个及之后的元素,查找时直接抛出NoSuchElementException。 - finally块逻辑错误,翻页被提前触发
finally块的执行规则是:无论try块内代码是正常跑完还是抛出异常,finally块代码一定会强制执行。你把异常捕获的except块全注释了,try块里j=11查找元素抛异常时,不会做任何等待、重试,直接中断for循环跳去执行finally里的翻页代码——这就是为什么控制台只打印到0 page 11 element就直接输出click,根本没跑完单页50个元素的遍历。 - 列表重复追加,存在大量冗余数据
你在for循环内部写了keyword_address_list.extend(now_list),每遍历1个元素就把当前已收集的当前页数据全量追加一次,加上finally块里又做了一次追加,最终爬取到的数据会有大量重复值。 - 字符串格式化占位符不匹配
你用%语法做xpath字符串格式化时,如果xpath模板里没有写对应的%d(整数占位符),而是写了${j}这类不识别的占位符,格式化时不会替换序号位置,生成的xpath路径完全不符合预期,自然找不到对应元素。你观察到的"本该传入10实际传入1",本质是循环被异常打断后翻页提前执行,页面状态和循环变量j的序号不匹配,不是格式化逻辑自己传错了值。 - 翻页等待逻辑不可靠
翻页后只写了固定2秒的sleep,如果页面加载慢,还没等元素渲染完成就开始查找,也会触发找不到元素的错误。
修复参考代码
import time from selenium import webdriver from webdriver_manager.chrome import ChromeDriverManager from selenium.webdriver.common.by import By from selenium.webdriver.support.ui import WebDriverWait from selenium.webdriver.support import expected_conditions as EC # 初始化驱动 driver = webdriver.Chrome(ChromeDriverManager().install()) wait = WebDriverWait(driver, 10) # 省略打开目标页面、切入结果iframe的前置逻辑 page_num = 0 keyword_address_list = [] max_crawl_page = 20 # 设置最大爬取页数,避免死循环 while page_num < max_crawl_page: current_page_items = [] # 遍历单页1-50个元素 for j in range(1, 51): print(f"{page_num} page {j} element") # 注意xpath模板里用%d作为整数占位符,替换为j的值 item_xpath = '//div[@class="result-item"][%d]' % j # 显式等待元素加载完成,替代固定等待 target_element = wait.until(EC.presence_of_element_located((By.XPATH, item_xpath))) target_text = target_element.text current_page_items.append(target_text) # 每10个元素滚动一次,注意加括号调用滚动方法 if j % 10 == 0: target_element.location_once_scrolled_into_view() time.sleep(0.5) # 单页所有元素爬取完成后,一次性追加到总列表,避免重复 keyword_address_list.extend(current_page_items) # 单页爬完再执行翻页 print("turn to next page") driver.switch_to.default_content() driver.switch_to.frame(result_frame) # 等待下一页按钮可点击后再点击 next_btn = wait.until(EC.element_to_be_clickable((By.XPATH, '{next button xpath}'))) next_btn.click() # 等待新页面第一个元素加载完成,确认翻页成功 wait.until(EC.presence_of_element_located((By.XPATH, '//div[@class="result-item"][1]'))) # 滚动回页面顶部 driver.execute_script("window.scrollTo(0, 0)") page_num += 1
内容的提问来源于stack exchange,提问作者timothy jeong
相关产品推荐
相关产品推荐

