Selenium爬取9gag帖子评论时子评论重复、漏抓问题求解
9gag评论区爬虫故障修复
故障根因
- 子评论数据重复
子评论定位使用全局XPath//*/div/section/section[2],匹配逻辑从页面根节点启动,始终返回页面中第一个符合规则的子评论区块,未限定在当前遍历的主评论节点范围内查找,导致遍历所有主评论时,抓取到的都是同一个子评论列表。 - 评论大面积漏抓
- 9gag评论区基于vue-recycle-scroller实现虚拟滚动,不在视口范围内的评论DOM会被组件直接销毁回收。固定步长滚动+全量抓取当前DOM节点的逻辑,会直接漏掉滚动过程中被回收的评论节点;且固定滚动到20000px的逻辑无法覆盖评论区全部加载高度。
- 点击展开子评论后未等待异步加载完成就抓取DOM,容易抓到空内容;同时使用评论文本作为字典唯一键,内容完全相同的不同评论会被判定为重复直接跳过。
- 多层裸
try-except直接吞掉所有报错,元素定位失败、点击拦截等异常完全无法感知,进一步放大漏抓问题。
- 初始定位失效
最早的定位代码将XPath语法字符串传入By.CSS_SELECTOR方法,二者语法规则不兼容,直接导致元素定位失败。
修复方案
- 修正子评论定位逻辑:查找子评论时使用相对XPath,路径前加
.限定从当前主评论节点向下查找,选择器替换为.//div[contains(@class,"comment-list-item__replies")]//div[contains(@class,"comment-list-item__text")],杜绝全局匹配导致的内容重复。 - 重构滚动加载逻辑:放弃固定步长滚动方案,循环滚动到评论区底部,直到"加载更多"按钮消失、页面高度不再增长为止;对每一个处理过的评论节点添加自定义标记,每次仅处理未打标的新评论节点,从根源避免虚拟滚动导致的漏抓、重复抓问题。
- 替换唯一标识规则:使用评论DOM自带的
data-comment-id属性作为每条评论的唯一key,该id为平台全局分配的唯一值,不会因为评论内容重复出现数据覆盖问题。 - 替换固定等待为显式等待:点击展开子评论、点击加载更多等操作后,使用
WebDriverWait等待目标DOM加载完成再执行后续抓取,既减少无效等待时长,也能避免抓不到异步加载的内容。 - 清理无意义的异常捕获:调试阶段删除裸
try-except,仅对已知可容错的异常(如评论已删除、无子评论)做捕获处理,方便快速定位运行时问题。
核心修复代码片段
# 子评论抓取核心逻辑(修复重复问题) if "comment-list-item__replies" in html: sub_comments_trigger = item.find_element(By.CSS_SELECTOR, "div.comment-list-item__replies") # 滚动到触发按钮位置避免点击拦截 driver.execute_script("arguments[0].scrollIntoViewIfNeeded(true);", sub_comments_trigger) time.sleep(0.3) sub_comments_trigger.click() # 等待子评论异步加载完成 WebDriverWait(driver, 3).until( EC.presence_of_element_located((By.XPATH, './/div[contains(@class,"comment-list-item__replies")]//div[contains(@class,"comment-list-item__text")]')) ) # 仅查找当前主评论下的子评论 sub_coms = item.find_elements(By.XPATH, './/div[contains(@class,"comment-list-item__replies")]//div[contains(@class,"comment-list-item__text")]') for com in sub_coms: sub_coms_list.append(com.text) # 用唯一comment-id存储数据 comment_id = item.get_attribute("data-comment-id") comments[comment_id] = { "content": comment, "replies": sub_coms_list }
内容的提问来源于stack exchange,提问作者naveen malla
相关产品推荐
相关产品推荐

