如何解决Python Selenium爬虫脚本获取冗余重复数据的问题
重复数据问题排查与解决方案
核心触发原因定位
- 最致命的逻辑bug:XPath定位参数完全失效
你当前写的定位XPath字符串没有任何格式占位符,末尾调用的.format(index)没有任何实际作用。无论循环索引走到1-19的哪个值,Selenium永远定位DOM中固定坐标位置的同一个元素,连续循环19次都是点击同一个商铺条目,这是产生全量重复数据的直接原因。
错误实现的问题对比:# 错误写法:字符串无占位符,format不会改变XPath内容 '//*[@id="pane"]/div/div[1]/div/div/div[5]/div[1]/div[1]'.format(index) # 修正后需要在动态匹配的位置添加占位符 '//*[@id="pane"]/div/div[1]/div/div/div[5]/div[1]/div[{}]'.format(index) - DOM顺序偏移导致的定位错位
从你使用的选择器可以判断,当前爬取目标为谷歌地图侧边栏的商铺列表。这类动态页面会在详情面板展开、滚动加载时实时调整DOM元素顺序:当你点开一个商铺的详情后,列表剩余条目的DOM下标会整体前移,此时按预设的数字索引循环点击,就会反复命中之前已经爬取过的条目。 - 无兜底去重逻辑
脚本没有维护已爬取条目的唯一标识库,哪怕定位逻辑完全正确,只要遇到页面动态渲染时的条目重复加载,就会把同一条数据重复写入CSV文件。
落地修正方案
- 先修正XPath的占位符逻辑,确保循环过程中每一次定位都会匹配当前索引对应的列表条目,彻底解决format失效的问题。
- 放弃固定数字索引的定位方式,改为基于元素集合的遍历逻辑,避免DOM顺序偏移导致的点错问题:
- 先定位整个搜索结果列表的父容器
- 直接获取容器下所有匹配商铺条目特征的元素集合
- 循环遍历集合中的元素对象执行点击操作,不再通过数字下标计算DOM位置
参考实现逻辑:
# 定位列表父容器 result_feed = driver.find_element(By.XPATH, '//div[@role="feed"]') # 获取所有可点击的商铺条目元素 all_business_items = result_feed.find_elements(By.XPATH, './/a[contains(@href, "/maps/place/")]') # 直接遍历元素对象执行操作 for item in all_business_items: driver.execute_script("arguments[0].click();", item) # 后续详情解析逻辑... - 增加全局去重兜底逻辑:
- 初始化一个全局空集合,用商铺标题+地址的拼接字符串作为条目的唯一标识
- 每次准备写入CSV前,先检查当前条目的唯一标识是否已存在集合中
- 已存在则直接跳过,不存在则将唯一标识加入集合后再执行写入
参考代码片段:
# 初始化全局已爬记录 crawled_records = set() # 详情解析完成后生成唯一键 unique_key = f"{title}_{address}" if unique_key in crawled_records: continue crawled_records.add(unique_key) # 执行CSV写入 writer.writerow([title, phone_number, website_url, email, address, ratings, reviewsCount, description]) - 优化等待逻辑替代固定
time.sleep(5):把固定等待替换为等待详情页核心元素(如标题标签)加载完成后再解析,避免因为页面加载延迟拿到上一个详情页的残留内容,造成数据重复。
内容的提问来源于stack exchange,提问作者deje
相关产品推荐
相关产品推荐

