Python中Selenium XPath获取元素无法存入列表并导出CSV问题排查
问题:Selenium爬取雅虎巴西新闻CSV重复同一组内容
我编写Python代码,通过Selenium访问雅虎巴西新闻网站,尝试用XPath提取所有文章的标题、副标题和链接,存入列表后导出为CSV,但导出的CSV中仅重复显示一组标题、副标题和链接,请问我哪里出错了?代码如下:
from selenium import webdriver from webdriver_manager.chrome import ChromeDriverManager from selenium.webdriver.chrome.service import Service from selenium.webdriver.common.by import By import pandas as pd servico = Service(ChromeDriverManager().install()) navegador = webdriver.Chrome(service=servico) url_do_site = "https://br.noticias.yahoo.com/" navegador.get(url_do_site) containers = navegador.find_elements(By.XPATH,'//li [@class ="js-stream-content Pos(r)"]') print(containers) titles = [] subtitles = [] links = [] for container in containers: title = container.find_element(By.XPATH,'//li [@class ="js-stream-content Pos(r)"]/div/div/div/h3/a/u').text subtitle = container.find_element(By.XPATH,'//li [@class ="js-stream-content Pos(r)"]/div/div/div/p').text link = container.find_element(By.XPATH,'//div [@class ="Cf"]/div /h3/a').get_attribute('href') titles.append(title) subtitles.append(subtitle) links.append(link) my_dict = {'title': titles, 'subtitle': subtitles, 'link': links} df_headlines = pd.DataFrame(my_dict) df_headlines.to_csv('headline.csv') navegador.quit()
问题原因与解决方法
核心问题
循环内的XPath使用了//开头,这会从整个文档的根节点开始查找元素,而不是从当前遍历的container节点下查找。所以每次循环都会匹配到页面中第一个符合条件的元素,最终导致所有列表项都是同一组内容。
修正方案
将循环内的XPath开头改为.,表示从**当前节点(即每个container)**开始相对查找:
修正后的代码
from selenium import webdriver from webdriver_manager.chrome import ChromeDriverManager from selenium.webdriver.chrome.service import Service 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 servico = Service(ChromeDriverManager().install()) navegador = webdriver.Chrome(service=servico) url_do_site = "https://br.noticias.yahoo.com/" navegador.get(url_do_site) # 等待页面加载完成,确保容器元素加载出来 wait = WebDriverWait(navegador, 10) containers = wait.until(EC.presence_of_all_elements_located((By.XPATH, '//li[@class="js-stream-content Pos(r)"]'))) titles = [] subtitles = [] links = [] for container in containers: # 使用相对路径(.//)从当前container节点开始查找 title = container.find_element(By.XPATH, './/h3/a/u').text # 部分文章可能没有副标题,加异常处理避免报错 try: subtitle = container.find_element(By.XPATH, './/div/div/p').text except: subtitle = "" link = container.find_element(By.XPATH, './/h3/a').get_attribute('href') titles.append(title) subtitles.append(subtitle) links.append(link) my_dict = {'title': titles, 'subtitle': subtitles, 'link': links} df_headlines = pd.DataFrame(my_dict) df_headlines.to_csv('headline.csv', index=False, encoding='utf-8-sig') navegador.quit()
额外优化点
- 添加等待机制:用
WebDriverWait等待元素加载完成,避免因页面未完全加载导致找不到元素的问题。 - 异常处理副标题:部分新闻可能没有副标题,加入
try-except防止代码崩溃。 - 简化XPath:不需要重复写完整的父节点路径,直接查找当前容器下的子元素即可,让代码更简洁。
- CSV编码优化:指定
encoding='utf-8-sig',避免导出后中文/特殊字符乱码。
内容的提问来源于stack exchange,提问作者ViniMarques10
相关产品推荐
相关产品推荐

