
本文介绍一种更高效、轻量的网页数据抓取方案:当目标数据已存在于初始html中时,优先使用 requests + lxml 替代 selenium,避免冗余的浏览器自动化操作,显著提升稳定性与执行速度。
本文介绍一种更高效、轻量的网页数据抓取方案:当目标数据已存在于初始html中时,优先使用 requests + lxml 替代 selenium,避免冗余的浏览器自动化操作,显著提升稳定性与执行速度。
在实际网页爬虫开发中,一个常见误区是“见到交互式页面就默认用 Selenium”。但正如本例所揭示的——访问 https://www.php.cn/link/e1a2719218ad9000036929229c99cd3a 时,尽管页面使用了手风琴(Accordion)组件折叠展示价格,所有治疗项目与费用均已在首次 HTTP 响应的 HTML 源码中静态存在,无需触发 JavaScript 展开动作。此时强行使用 Selenium 不仅增加复杂度(需处理 Cookie 弹窗、元素点击、隐式等待等),还易因 DOM 加载时机或元素定位偏差导致失败。
✅ 推荐方案:requests + lxml(静态解析)
该组合轻量、快速、稳定,适用于绝大多数服务端渲染(SSR)页面。以下是完整可运行代码:
import requests
from lxml import html
# 1. 发起 HTTP 请求获取原始 HTML
url = "https://www.php.cn/link/e1a2719218ad9000036929229c99cd3a"
response = requests.get(url, timeout=10)
response.raise_for_status() # 确保请求成功
# 2. 解析 HTML 文档
tree = html.fromstring(response.text)
# 3. 定位价格表格行(<tr>),逐行提取第一列(项目名)和第二列(价格)
dental_fees = []
for row in tree.xpath('//div[contains(@class, "pricing")]//tr'):
try:
# 使用 .xpath('./td[1]/text()') 精确匹配当前行下的单元格文本
product = row.xpath('./td[1]/text()')[0].strip()
price = row.xpath('./td[2]/text()')[0].strip()
dental_fees.append({"Title": product, "Price": price})
print(f"✓ {product} → {price}")
except (IndexError, AttributeError):
# 跳过表头、空行或格式异常的行
continue
print(f"\n✅ 共提取 {len(dental_fees)} 条有效价格数据。")? 关键说明与注意事项:
为什么不用 Selenium?
原代码中尝试点击 .material-icons 展开所有 Accordion,但该选择器实际匹配多个非折叠控件(如返回箭头),且 driver.find_element(By.CLASS_NAME,'accordion-content') 会返回首个匹配元素而非每个区块的内容,导致数据重复或遗漏。Selenium 在此场景下属于“高射炮打蚊子”。-
XPath 定位逻辑解析:
//div[contains(@class, "pricing")]//tr 精准锁定价格区域内的所有表格行;./td[1] 和 ./td[2] 使用相对路径(./)确保从当前节点出发,避免跨行误读。 健壮性增强建议:
- 添加 timeout 和 raise_for_status() 防止网络异常静默失败;
- 使用 try/except 捕获 IndexError(如空
)和 AttributeError(如节点无文本); - 对 strip() 结果做空值校验(如 if product and price:)可进一步过滤脏数据。
依赖安装(一次执行):
pip install requests lxml
? 总结:
判断是否使用 Selenium 的黄金标准是——目标数据是否依赖客户端 JavaScript 动态生成? 若答案为否(如本例),请坚定选择 requests + lxml(或 BeautifulSoup)。它更快、更稳、更易调试,也更符合工程化爬虫的最佳实践。真正的自动化,始于对网页渲染机制的准确理解。










