Selenium滚动爬取JS渲染网页仅获取前8条商品数据的问题求解
代码调整方案
现存问题
你当前逻辑只抓到顶部8个商品,本质是几个逻辑偏差导致的:
- 滚动高度取的参照前后不统一:初始化时拿
document.documentElement.scrollHeight做基准,循环里却用document.body.scrollHeight做对比,在存在非全局滚动容器的页面上,两个值根本对不上,系统会直接判定已经滚到底,退出循环,根本不会触发后面的商品加载。 - 滚动容器不对:这类电商站的商品列表不是挂在全局页面上滚动的,是独立的DOM容器自己带滚动条,你直接执行
window.scrollTo(0, document.body.scrollHeight)根本碰不到列表的滚动区域,自然不会触发分页加载。 - 硬等20秒的逻辑不靠谱:固定等待时长要么不够久,新商品没渲染出来就开始算高度,要么等太久浪费时间,卡不准无限滚动的触发时机。
- 选元素用的类名带随机hash:你写的
fWFKvm、fQbbTY这类后缀是前端打包时生成的随机值,每次发版就会变,就算商品正常加载了,也可能因为类名对不上抓不到。
调整方向
- 别再靠整个页面的高度判断加载进度了,直接统计当前已经渲染出来的商品节点数量,等数量不再增长的时候,就说明所有商品都加载完了。
- 滚动的时候直接定位到当前最后一个已加载的商品位置,把它滚到视口中间,不管列表是哪个容器承载的,都能触发对应的懒加载逻辑。
- 把固定sleep换成显式等待,每次滚动后等新的商品节点出现,再进入下一轮循环,不用卡死等20秒。
- 写选择器的时候别带类名末尾的随机hash,用属性包含匹配的方式,比如找带
MarketplaceProductList__Wrapper前缀的元素就行,避免类名变了抓不到。
调整后的参考代码
from selenium.webdriver.common.by import By from selenium.webdriver.support.ui import WebDriverWait from selenium.webdriver.support import expected_conditions as EC url = 'https://www.faire.com/retailer/r_9vkjixqbpq/category/Beauty%20&%20Wellness/subcategory/Bath%20&%20Body?filters=sorting%3Afeatured' wd.get(url) # 等首个商品列表渲染出来 WebDriverWait(wd, 15).until( EC.presence_of_element_located((By.CSS_SELECTOR, '[class*="MarketplaceProductList__Wrapper"]')) ) last_count = 0 wait = WebDriverWait(wd, 20) while True: current_products = wd.find_elements(By.CSS_SELECTOR, '[class*="MarketplaceProductList__TileWrapper"]') current_count = len(current_products) # 连续两次数量没变化,就说明没有新商品加载了 if current_count == last_count: break last_count = current_count # 滚到最后一个已加载的商品位置,触发后续分页 wd.execute_script("arguments[0].scrollIntoView({block: 'center'});", current_products[-1]) # 等新的商品加载出来,再进入下一轮 wait.until(lambda d: len(d.find_elements(By.CSS_SELECTOR, '[class*="MarketplaceProductList__TileWrapper"]')) > last_count) # 全量加载完成后再提取内容 soup = BeautifulSoup(wd.page_source, 'lxml') listings = soup.select('div[class*="MarketplaceProductList__TileWrapper"]') for item in listings: product_name = item.select_one('span[class*="FallbackHandler__ContentParentWrapper"]').get_text(strip=True) print(product_name)
这个逻辑绕开了“找不对滚动容器”“高度算不准”的常见坑,不管页面是全局滚动还是内部容器滚动,只要能看到最后一个商品的位置,就能触发懒加载;同时选择器不依赖随机生成的类名后缀,兼容性更强。
内容的提问来源于stack exchange,提问作者codinggirl
相关产品推荐
相关产品推荐

