You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Python Selenium for循环中动态拼接XPath爬取数据问题求解

Selenium循环拼接动态XPath抓取表格数据解决方案

问题背景

使用Python+Selenium开展网页数据抓取,目标是从加拿大统计局贸易数据查询页面提取表格内容,需要在for循环中传入动态行号参数拼接XPath,逐行定位单元格元素。
目标页面:加拿大统计局贸易进口数据查询页

原代码存在的核心错误

  • 拼写错误:循环方法误写为rane(25),正确方法为range(),且原写法未指定起始值,默认从0开始计数,和表格行号从1开始的规则不匹配
  • 语法错误:XPath字符串外层用双引号包裹,内部属性选择器id="report_table"也使用双引号,会直接导致字符串截断报错;整数类型的循环变量直接用+和字符串拼接,会触发类型不匹配错误
  • 逻辑错误:循环内首个元素定位硬编码为tr[1],未使用动态行号,每次循环只会重复抓取第一行内容,完全无法实现逐行遍历
  • 输出错误:直接打印定位到的WebElement对象,只能拿到对象内存地址,无法获取单元格实际文本内容
  • 冗余代码:循环前提前赋值cel = 1无实际作用,for循环遍历过程中会自动覆盖该变量

修正后完整代码

from selenium import webdriver
from selenium.webdriver.common.by import By
import time

# 初始化浏览器(高版本Selenium不需要手动指定chromedriver路径,若本地驱动配置异常可自行补全executable_path参数)
driver = webdriver.Chrome()
driver.get('https://www150.statcan.gc.ca/n1/pub/71-607-x/71-607-x2021004-eng.htm')
time.sleep(2)

# 点击导入数据入口
button = driver.find_element(By.XPATH, '//*[@id="cimt_import"]/p[1]/a')
button.click()
time.sleep(2)

# 点击对应主题
button = driver.find_element(By.XPATH, '//*[@id="topic3s"]')
button.click()
time.sleep(2)

# 选择起始年月
driver.find_element(By.XPATH, '//*[@id="fromYear"]/option[1]').click()
driver.find_element(By.XPATH, '//*[@id="fromMonth"]/option[1]').click()
# 选择结束年月
driver.find_element(By.XPATH, '//*[@id="toYear"]/option[1]').click()
driver.find_element(By.XPATH, '//*[@id="toMonth"]/option[5]').click()
# 选择商品章节
driver.find_element(By.XPATH, '//*[@id="report_hs"]/option[1]').click()
time.sleep(1)
# 选择具体商品
driver.find_element(By.XPATH, '//*[@id="report_hs"]/option[2]').click()
# 点击生成报告
driver.find_element(By.XPATH, '//*[@id="report"]/div[1]/div[3]/div[5]/p[2]/button').click()
time.sleep(3) # 等待表格加载完成,可替换为显式等待提升稳定性

# 循环遍历表格前25行
for row_num in range(1, 26):
    # 拼接动态XPath,外层用单引号包裹,内部属性用双引号避免冲突
    commodity_link = driver.find_element(By.XPATH, f'//*[@id="report_table"]/tbody/tr[{row_num}]/td[2]/a')
    # 打印商品名称
    print(commodity_link.text)
    # 取第4列内容
    col4 = driver.find_element(By.XPATH, f'//*[@id="report_table"]/tbody/tr[{row_num}]/td[4]').text
    print(col4)
    # 取第7列内容
    col7 = driver.find_element(By.XPATH, f'//*[@id="report_table"]/tbody/tr[{row_num}]/td[7]').text
    print(col7)
    # 取第8列abbr标签内容
    col8_abbr = driver.find_element(By.XPATH, f'//*[@id="report_table"]/tbody/tr[{row_num}]/td[8]/abbr').text
    print(col8_abbr)
    print('---'*20)

time.sleep(3)
driver.quit()

关键编写要点

  • 动态拼接XPath优先使用f-string语法,比+拼接可读性更高,且会自动处理数字到字符串的类型转换,避免类型报错
  • 严格注意引号嵌套规则:如果XPath外层用单引号包裹,内部属性值就用双引号;如果外层用双引号,内部就用单引号,绝对不能内外使用相同引号导致字符串提前截断
  • 高版本Selenium已废弃find_element_by_xpath这类旧写法,统一使用find_element(By.XPATH, 路径)的新语法,需要提前导入By类
  • 表格遍历更稳定的写法是先一次性定位所有行元素:rows = driver.find_elements(By.XPATH, '//*[@id="report_table"]/tbody/tr'),再遍历rows列表取索引,避免逐行定位时因为页面加载、行号不连续导致的定位失败
  • 固定时长的time.sleep()可替换为Selenium显式等待,判断表格加载完成后再执行抓取,能大幅提升脚本运行速度和稳定性

内容的提问来源于stack exchange,提问作者user16832397

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.26 11:18:15