使用Python Selenium爬取RealSelf图片时翻页后图片重复的问题求助
问题分析与解决建议
核心问题原因
- 元素列表未重新获取:翻页后你没有重新查找
before_images和after_images,而是复用了第一页的旧元素引用,导致始终读取第一页的图片 - 文件名重复覆盖:每个页面的图片都用
image{index}.jpg命名,index从0开始,后面页面的图片会直接覆盖前面页面的同名文件 - 等待机制不够可靠:依赖
time.sleep可能导致页面未完全加载就开始抓取,而懒加载图片可能还没切换到lazyloaded状态
具体修复方案
1. 翻页后重新定位元素
每次进入新页面后,必须重新调用find_elements获取当前页面的图片元素,不能复用之前的列表。
2. 文件名加入页码避免覆盖
将页码page_num加入文件名,比如image{page_num}_{index}.jpg,这样不同页面的图片不会互相覆盖。
3. 用显式等待替代固定sleep
等待页面加载完成、图片元素出现且处于lazyloaded状态,比固定时间sleep更稳定。
4. 优化懒加载图片的处理
确保图片加载完成后再获取src,可以等待元素的class包含lazyloaded。
修改后的完整代码
from selenium import webdriver from selenium.webdriver.common.by import By from selenium.webdriver.chrome.options import Options from selenium.webdriver.support.ui import WebDriverWait from selenium.webdriver.support import expected_conditions as EC import urllib.request import os # 自动创建保存目录,不存在则新建 os.makedirs("dermal-fillers/before", exist_ok=True) os.makedirs("dermal-fillers/after", exist_ok=True) options = Options() options.add_argument("start-maximized") options.add_argument("disable-infobars") options.add_argument("--disable-extensions") driver = webdriver.Chrome(options=options, executable_path=r'D:\program\driver\chromedriver.exe') driver.get("https://www.realself.com/photos/dermal-fillers#page=1&tags=&location=2038") # 等待初始页面图片元素加载 WebDriverWait(driver, 20).until(EC.presence_of_element_located((By.CLASS_NAME, "fixed-img2"))) driver.execute_script("window.scrollTo(0, document.body.scrollHeight);") # 等待懒加载图片加载完成 WebDriverWait(driver, 10).until(EC.presence_of_element_located((By.CLASS_NAME, "lazyloaded"))) # 遍历页面 for page_num in range(1, 283): print(f'开始保存第 {page_num} 页的图片') # 重新获取当前页面的前后图片元素(关键步骤:每次翻页后重新定位) before_images = WebDriverWait(driver, 20).until( EC.presence_of_all_elements_located((By.XPATH, "//div[@class='fixed-img2'][1]")) ) after_images = WebDriverWait(driver, 20).until( EC.presence_of_all_elements_located((By.XPATH, "//div[@class='fixed-img2'][2]")) ) # 保存before图片 for index, before_image in enumerate(before_images): try: # 等待当前图片加载为lazyloaded状态 img_element = WebDriverWait(before_image, 10).until( EC.presence_of_element_located((By.CLASS_NAME, "lazyloaded")) ) image_source = img_element.get_attribute('src') print(f'before image: {image_source}') # 文件名加入页码,避免不同页面图片覆盖 urllib.request.urlretrieve(image_source, f"dermal-fillers/before/image{page_num}_{index}.jpg") except Exception as e: print(f'第 {page_num} 页第 {index} 张before图片出错: {str(e)}') # 保存after图片 for index, after_image in enumerate(after_images): try: img_element = WebDriverWait(after_image, 10).until( EC.presence_of_element_located((By.CLASS_NAME, "lazyloaded")) ) image_source = img_element.get_attribute('src') print(f'after image: {image_source}') urllib.request.urlretrieve(image_source, f"dermal-fillers/after/image{page_num}_{index}.jpg") except Exception as e: print(f'第 {page_num} 页第 {index} 张after图片出错: {str(e)}') # 跳转到下一页(最后一页无需点击) if page_num < 282: next_btn = WebDriverWait(driver, 30).until( EC.element_to_be_clickable((By.CLASS_NAME, "Pager-forward")) ) driver.execute_script("arguments[0].scrollIntoView(true);", next_btn) next_btn.click() # 等待页码更新,确认页面切换成功 WebDriverWait(driver, 20).until( EC.text_to_be_present_in_element((By.CLASS_NAME, "Pager-current"), str(page_num+1)) ) # 等待新页面图片加载完成 WebDriverWait(driver, 20).until( EC.presence_of_element_located((By.CLASS_NAME, "lazyloaded")) ) print(f'已跳转到第 {page_num+1} 页') driver.quit() print('任务结束')
额外注意事项
- 确保
chromedriver版本与你的Chrome浏览器版本匹配,避免兼容性问题 - 频繁抓取可能触发网站反爬机制,建议适当增加等待时间,或者加入随机延迟
- 检查网站的
robots.txt,确保你的抓取行为符合网站规则(大学项目建议先确认合规性)
内容的提问来源于stack exchange,提问作者morteza eskandarian
相关产品推荐
相关产品推荐

