嵌套循环中DataFrame拼接异常:爬虫仅保留内层循环数据的修复方案
问题分析与修复方案
核心问题
find_elements不触发异常:你使用的wd.find_elements()方法在找不到目标元素时,只会返回空列表,不会抛出NoSuchElementException。这导致当页面没有多规格元素时,代码既不会执行内层循环,也不会进入except块,直接跳过了单个价格的提取逻辑——这就是外层数据丢失的根本原因。- 列名大小写不匹配:初始DataFrame的列名为
Price,但后续拼接数据用的是PRICE,大小写不一致会导致数据被存入新列,看起来像是数据丢失。
修复方案
方案1:修正逻辑判断(解决数据丢失问题)
将原有的try-except结构改为判断元素列表是否为空的逻辑,同时统一列名:
import pandas as pd from selenium.common.exceptions import NoSuchElementException df = pd.DataFrame(columns=['Price']) # 开始爬取 for url in card_link_list: wd.get(url) # 获取多规格元素列表(find_elements不会抛异常,找不到则返回空列表) pack_sizes_elements = wd.find_elements(By.XPATH, "//div[@class='_1LiCn']/div") if pack_sizes_elements: # 存在多规格时批量提取价格 for element in pack_sizes_elements: element.click() price = element.find_element(By.XPATH, ".//span[@class='_2j_7u']").text.strip() # 统一列名为'Price' df = pd.concat([df, pd.DataFrame([{'Price': price}])]) else: # 无多规格时提取单个价格 try: price = wd.find_element(By.XPATH, "//td[@data-qa='productPrice']").text.strip() df = pd.concat([df, pd.DataFrame([{'Price': price}])]) except NoSuchElementException: # 可选:记录提取失败的URL,便于排查 print(f"无法提取URL {url} 的价格")
方案2:高效的DataFrame构建方式(推荐)
频繁调用pd.concat会重复创建新的DataFrame,性能极低(尤其数据量较大时)。推荐先将所有数据存入列表,最后一次性生成DataFrame:
import pandas as pd from selenium.common.exceptions import NoSuchElementException price_records = [] # 用列表暂存所有价格数据 # 开始爬取 for url in card_link_list: wd.get(url) pack_sizes_elements = wd.find_elements(By.XPATH, "//div[@class='_1LiCn']/div") if pack_sizes_elements: for element in pack_sizes_elements: element.click() try: price = element.find_element(By.XPATH, ".//span[@class='_2j_7u']").text.strip() # 可额外添加URL字段,方便后续排查 price_records.append({'Price': price, 'URL': url}) except NoSuchElementException: print(f"URL {url} 下某规格价格提取失败") else: try: price = wd.find_element(By.XPATH, "//td[@data-qa='productPrice']").text.strip() price_records.append({'Price': price, 'URL': url}) except NoSuchElementException: print(f"URL {url} 价格提取失败") # 一次性生成DataFrame df = pd.DataFrame(price_records)
额外优化建议
- 添加显式等待:页面加载可能存在延迟,使用
WebDriverWait等待元素加载完成,避免因元素未渲染导致的提取失败:from selenium.webdriver.support.ui import WebDriverWait from selenium.webdriver.support import expected_conditions as EC # 等待多规格元素出现,最长等待10秒 pack_sizes_elements = WebDriverWait(wd, 10).until( EC.presence_of_all_elements_located((By.XPATH, "//div[@class='_1LiCn']/div")) ) - 异常处理细化:针对不同的异常场景添加对应的处理逻辑,比如元素点击失败、文本提取失败等,提升代码稳定性。
内容的提问来源于stack exchange,提问作者yash agarwal
相关产品推荐
相关产品推荐

