如何使用Selenium与Python实现双下拉列表自动遍历爬取通行费率数据
收费站费率爬取逻辑改造实现
核心遍历逻辑
采用双层嵌套循环结构实现全量数据提取,逻辑链路为:
- 外层循环遍历收费站下拉框的所有有效选项,每选中一个收费站后等待页面加载
- 内层循环遍历当前站点下车辆类型下拉框的所有有效选项,每选中一个车型后等待费率表格渲染完成
- 提取当前展示场景下的轴数、费率数据,关联当前选中的收费站名称、车型名称做结构化存储
- 内层所有车型遍历完成后,自动进入下一个收费站的遍历流程,直到所有选项处理完毕
改造后可运行代码
from datetime import date from selenium import webdriver from selenium.webdriver.support.ui import Select from selenium.webdriver.common.by import By from selenium.webdriver.support.ui import WebDriverWait from selenium.webdriver.support.ui import expected_conditions as EC import time # 初始化驱动配置 today = str(date.today()) PATH = 'C:\Program Files (x86)\chromedriver.exe' driver = webdriver.Chrome(PATH) # 设置最长10秒等待,避免页面加载延迟导致的元素定位失败 wait = WebDriverWait(driver, 10) try: # 打开目标站点 driver.get('http://www.triunfoconcebra.com.br/home') # 滚动到费率表格区域 table = driver.find_element(By.XPATH, '//div[@class="tarifas txt-center"]') table.location_once_scrolled_into_view # 初始化两个下拉选择器 toll_select = Select(driver.find_element(By.ID, 'ctl00_cphContent_ddlPracas')) vehicle_select = Select(driver.find_element(By.ID, 'ctl00_cphContent_ddlTipoTarifa')) # 提前获取所有下拉的有效选项(跳过第一个占位提示选项) toll_options = [opt for opt in toll_select.options if opt.get_attribute('value') != ''][1:] vehicle_options = [opt for opt in vehicle_select.options if opt.get_attribute('value') != ''][1:] # 初始化结构化数据存储列表 extracted_data = [] # 外层遍历所有收费站 for toll_opt in toll_options: toll_name = toll_opt.text toll_select.select_by_visible_text(toll_name) # 等待收费站切换完成 time.sleep(1) # 内层遍历当前站点下的所有车型 for veh_opt in vehicle_options: veh_type = veh_opt.text vehicle_select.select_by_visible_text(veh_type) # 等待费率表格加载完成 wait.until(EC.presence_of_element_located((By.XPATH, '//div[@class="left eixo bg-branco" or @class="left eixo bg-cinza"]'))) time.sleep(0.5) # 提取当前场景下的轴数数据 axles = driver.find_elements(By.XPATH, '//div[@class="left eixo bg-branco" or @class="left eixo bg-cinza"]') # 提取当前场景下的费率数据 prices = driver.find_elements(By.XPATH, '//div[@class="left valor bg-branco" or @class="left valor bg-cinza"]') # 逐行匹配轴数和对应费率,存入结构化数据 for axle_elem, price_elem in zip(axles, prices): axle_num = axle_elem.find_element(By.XPATH, './span').text fee = price_elem.text extracted_data.append({ "query_date": today, "toll_station": toll_name, "vehicle_type": veh_type, "axle_count": axle_num, "fee": fee }) finally: # 无论执行是否出错,最终关闭浏览器 driver.quit() # 打印提取结果校验 print(f"共提取有效费率记录{len(extracted_data)}条")
关键优化说明
- 替换了原代码中已废弃的老旧Selenium定位API(如
find_element_by_id、find_element_by_xpath),使用标准的By定位方式兼容最新版本Selenium - 增加了合理的页面等待逻辑,避免因为AJAX异步加载导致的元素定位失败、取数错误
- 采用结构化字典存储每条数据的关联字段,避免原代码中零散追加全局列表导致的字段错位问题
- 自动过滤下拉框中的占位提示选项,避免触发无效的页面查询
内容的提问来源于stack exchange,提问作者Obed Marquez
相关产品推荐
相关产品推荐

