如何用Selenium抓取iframe中全部评论并导出至CSV/XML?
解决iframe评论抓取与内容清理问题
我来帮你搞定这两个问题,直接上实用方案:
1. 抓取所有评论并导出为CSV/XML格式
你当前代码只能抓到单条评论,是因为用了固定的评论ID(cmt66363941),而且没处理评论区的滚动加载(很多网站评论是滑到底部才会加载更多)。调整思路后,完整实现步骤如下:
- 切换到评论iframe后,循环滚动页面直到没有新评论加载
- 定位所有评论的容器元素,遍历提取每条评论的用户名和内容
- 用
pandas快速导出CSV,或者用Python内置库生成XML
修改后的可运行代码:
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 import pandas as pd import time import re driver = webdriver.Chrome() driver.get("https://finance.detik.com/berita-ekonomi-bisnis/d-5307853/ri-disebut-punya-risiko-korupsi-yang-tinggi?_ga=2.13736693.357978333.1608782559-293324864.1608782559") # 切换到评论iframe iframe = WebDriverWait(driver, 20).until(EC.presence_of_element_located((By.XPATH, "//iframe[@class='xcomponent-component-frame xcomponent-visible']"))) driver.switch_to.frame(iframe) # 滚动加载所有评论(处理懒加载) last_height = driver.execute_script("return document.body.scrollHeight") while True: driver.execute_script("window.scrollTo(0, document.body.scrollHeight);") time.sleep(2) # 给页面留加载时间 new_height = driver.execute_script("return document.body.scrollHeight") if new_height == last_height: break # 没有新内容加载,退出循环 last_height = new_height # 定位所有评论容器(所有ID以cmt开头的div) comments = WebDriverWait(driver, 20).until(EC.presence_of_all_elements_located((By.XPATH, "//div[starts-with(@id, 'cmt')]"))) # 存储评论数据 data = [] for comment in comments: # 提取用户名(包含发布时间) username_elem = comment.find_element(By.XPATH, "./div[1]/div[1]") username = username_elem.text.strip() # 提取并清理评论内容 comment_elem = comment.find_element(By.XPATH, "./div[1]/div[2]") raw_comment = comment_elem.text.strip() # 移除末尾的无关操作文本 clean_comment = re.sub(r"\s*(Laporkan|Balas|Bagikan).*$", "", raw_comment).strip() data.append({"username": username, "comment": clean_comment}) # 导出为CSV文件 df = pd.DataFrame(data) df.to_csv("detik_comments.csv", index=False, encoding="utf-8") # 导出为XML文件(可选) import xml.etree.ElementTree as ET root = ET.Element("comments") for item in data: comment_item = ET.SubElement(root, "comment") ET.SubElement(comment_item, "username").text = item["username"] ET.SubElement(comment_item, "content").text = item["comment"] tree = ET.ElementTree(root) tree.write("detik_comments.xml", encoding="utf-8", xml_declaration=True) driver.quit()
2. 移除输出中的无关内容(如「Laporkan 2BalasBagikan:」)
这类内容是评论区的操作按钮文本,会被误抓到评论内容里。上面的代码已经集成了清理逻辑,核心思路是用正则表达式匹配并移除末尾的操作类文本:
import re clean_comment = re.sub(r"\s*(Laporkan|Balas|Bagikan).*$", "", raw_comment).strip()
如果只需要处理「Laporkan 2BalasBagikan:」这一种情况,也可以用更简单的字符串分割:
clean_comment = raw_comment.split("Laporkan")[0].strip()
内容的提问来源于stack exchange,提问作者Hanif
相关产品推荐
相关产品推荐

