Selenium结合BeautifulSoup爬取Instagram图片出现重复结果的解决方法
解决Instagram爬虫重复图片的问题
看起来你碰到了动态页面爬虫里非常典型的两个问题:重复抓取和内容加载不完整,我来给你拆解一下针对性的解决方案:
核心问题分析
- 重复抓取根源:Instagram滚动加载时,之前渲染的图片元素不会从DOM中移除,每次循环爬取时BeautifulSoup会把旧的img链接也一并抓取,自然会出现重复下载。
- 加载不完整原因:如果把爬取逻辑移到滚动循环外,你可能只触发了初始的30张图片加载,没有持续滚动触发后续的动态内容,所以只能拿到前30张。
具体解决方案
1. 用集合维护已爬取URL(最直接的去重手段)
Python的集合(set)天生具备自动去重特性,每次爬取到新的图片链接时,先检查是否已经存在于集合中,只有未出现过的链接才进行下载操作,从根源上避免重复。
2. 优化Selenium滚动与加载逻辑
要确保每次滚动都能触发新内容加载,并且准确判断何时停止滚动:
- 记录每次滚动前的页面高度,滚动后对比新高度,如果高度不变,说明已经到页面底部,终止循环。
- 滚动后不要立刻爬取,用显式等待替代固定sleep,确保新图片元素完全渲染到DOM后再解析,避免漏抓。
3. 结合两者的完整代码示例
from selenium import webdriver from selenium.webdriver.common.by import By from selenium.webdriver.support.ui import WebDriverWait from selenium.webdriver.support import expected_conditions as EC from bs4 import BeautifulSoup import requests import os import random import time # 初始化浏览器 driver = webdriver.Chrome() target_url = "https://www.instagram.com/目标账号/" driver.get(target_url) # 存储已爬取的图片URL,自动去重 seen_img_urls = set() last_scroll_height = driver.execute_script("return document.body.scrollHeight") download_dir = "instagram_images" os.makedirs(download_dir, exist_ok=True) while True: # 滚动到页面底部 driver.execute_script("window.scrollTo(0, document.body.scrollHeight);") # 显式等待新图片加载(比固定sleep更可靠,适配不同网络速度) try: WebDriverWait(driver, 10).until( EC.presence_of_all_elements_located((By.CSS_SELECTOR, "article img")) ) except: # 超时说明无新内容,退出循环 break # 随机延迟,降低被反爬概率 time.sleep(random.uniform(1, 2.5)) # 解析当前页面HTML soup = BeautifulSoup(driver.page_source, "html.parser") # 精准定位帖子内的图片,避免抓取头像、logo等无关元素 img_tags = soup.select("article img") # 处理每个图片链接 for img in img_tags: # 优先抓取高清图:srcset中最后一个链接通常是最高分辨率版本 img_srcset = img.get("srcset") if img_srcset: img_url = img_srcset.split(",")[-1].split()[0] else: img_url = img.get("src") if img_url and img_url not in seen_img_urls: seen_img_urls.add(img_url) # 下载图片 try: response = requests.get(img_url, stream=True, headers={"User-Agent": "Mozilla/5.0"}) response.raise_for_status() # 用URL哈希值作为文件名,避免重名 filename = os.path.join(download_dir, f"{hash(img_url)}.jpg") with open(filename, "wb") as f: for chunk in response.iter_content(chunk_size=8192): f.write(chunk) print(f"已下载: {filename}") except Exception as e: print(f"下载失败 {img_url}: {str(e)}") # 检查是否到达页面底部 new_scroll_height = driver.execute_script("return document.body.scrollHeight") if new_scroll_height == last_scroll_height: break last_scroll_height = new_scroll_height driver.quit() print(f"爬取完成,共下载{len(seen_img_urls)}张不重复图片")
额外优化建议
- 精准选择器:用
article img只定位帖子内的图片,避免抓取页面上的头像、导航栏图标等无关内容。 - 反爬规避:添加随机延迟、设置User-Agent,必要时可以模拟登录(针对私密账号)。
- 异常处理:给网络请求添加异常捕获,避免单个图片下载失败导致整个脚本中断。
内容的提问来源于stack exchange,提问作者P_n
相关产品推荐
相关产品推荐

