Selenium爬取Bershka页面遇NameError及产品统计异常求助
Bershka网站产品爬取问题解决
一、NameError: name 'sosete' is not defined 错误排查
出现这个错误的核心原因是**driver.find_elements(By.CLASS_NAME, "grid-item normal")无法获取到任何元素**,导致product是空列表,for循环根本没有执行,后续涉及sosete的逻辑自然触发变量未定义错误。具体问题点:
By.CLASS_NAME仅支持单个类名,不能同时传入多个类("grid-item"和"normal"是两个独立类),需改用CSS选择器.grid-item.normal定位多类元素。- XPATH的字符串拼接逻辑错误,你写的
'//*[@id="main-content"]/div/div/div[2]/section[1]/div/ul/li["+str(z+1)+"]/div'会把"+str(z+1)+"当成字面量,无法正确替换变量,应使用f-string格式化:f'//*[@id="main-content"]/div/div/div[2]/section[1]/div/ul/li[{z+1}]/div'。 - 隐式等待位置错误,它是全局生效的等待策略,应在初始化driver后立即设置,而非点击cookie之后。
修正后的代码片段:
import time from selenium import webdriver from selenium.webdriver.chrome.service import Service from selenium.webdriver.chrome.options import Options from selenium.webdriver.common.by import By from selenium.webdriver.common.action_chains import ActionChains options = webdriver.ChromeOptions() options.add_experimental_option("detach", True) options.add_argument("start-maximized") webdriver_service = Service(r'C:\webdrivers\chromedriver.exe') # 用原始字符串避免路径转义问题 driver = webdriver.Chrome(options=options, service=webdriver_service) driver.implicitly_wait(10) # 全局隐式等待提前设置 driver.get("https://www.bershka.com/ro/femeie/accesorii/%C8%99osete-c1010194004.html") # 处理cookie和地区选择 cookies_bttn = driver.find_element(By.ID, "onetrust-accept-btn-handler") cookies_bttn.click() country_save = driver.find_element(By.CSS_SELECTOR, "#geoblocking > div > div > div.select-country-container > button.button.is-sm.confirm") country_save.click() hoover = ActionChains(driver) # 改用CSS选择器定位产品元素 product = driver.find_elements(By.CSS_SELECTOR, ".grid-item.normal") z = 0 for sosete in product: # 修正XPATH的变量拼接 sth = sosete.find_element(By.XPATH, f'//*[@id="main-content"]/div/div/div[2]/section[1]/div/ul/li[{z+1}]/div') z += 1 print(len(sth))
二、产品数量统计不全(仅20个,实际31个)的解决
这个问题源于Bershka列表页采用滚动加载机制,初始仅渲染20个产品,剩余产品需滚动页面至底部才会加载。需先模拟滚动加载所有产品,再进行数量统计。
修正后的统计代码:
# 滚动页面到底部,加载所有产品 def scroll_to_load_all(driver): last_height = driver.execute_script("return document.body.scrollHeight") while True: driver.execute_script("window.scrollTo(0, document.body.scrollHeight);") time.sleep(2) # 预留加载时间 new_height = driver.execute_script("return document.body.scrollHeight") if new_height == last_height: break last_height = new_height # 先执行滚动加载 scroll_to_load_all(driver) # 再统计产品数量 whole_product = driver.find_elements(By.CLASS_NAME, "grid-card-link") print(f"实际产品数量:{len(whole_product)}") # 批量点击快速购买按钮的修正(需先加载所有元素) i = 0 # 获取所有产品图片元素 products = driver.find_elements(By.CLASS_NAME, "product-image") for product in products: hoover.move_to_element(product).perform() # 需调用perform()执行动作 time.sleep(0.5) # 定位当前产品的快速购买按钮(避免定位到全局所有按钮) purchase_bttn = product.find_element(By.CLASS_NAME, "quick-purchase") purchase_bttn.click() time.sleep(1) i += 1 print(f"点击了{i}个快速购买按钮")
额外提示
- 路径字符串建议用原始字符串(加r前缀),避免
\w这类转义字符导致路径错误。 - ActionChains的动作必须调用
perform()才会执行,之前的代码未执行该方法,所以无法触发快速购买按钮显示。 - 尽量避免使用绝对XPATH,页面结构变化时极易失效,优先选择CSS选择器或相对XPATH。
内容的提问来源于stack exchange,提问作者user20468552
相关产品推荐
相关产品推荐

