
本文介绍在目标网页依赖 JavaScript 事件(如点击 div)才加载答案内容时,如何绕过 BeautifulSoup 的局限性,改用轻量、现代的 Selenium 方案完成动态页面抓取,尤其适配 Ubuntu 环境且无需手动管理 ChromeDriver。
本文介绍在目标网页依赖 javascript 事件(如点击 `div`)才加载答案内容时,如何绕过 beautifulsoup 的局限性,改用轻量、现代的 selenium 方案完成动态页面抓取,尤其适配 ubuntu 环境且无需手动管理 chromedriver。
BeautifulSoup 是一个强大的静态 HTML 解析库,但它无法执行 JavaScript,因此对“点击后才显示内容”的交互式网页(例如 <div onclick="showAnswers()">Xem đáp án</div>)完全无效。这类场景必须借助浏览器自动化工具——而 Selenium 正是业界标准方案。
幸运的是,现代 Selenium(v4.11+)已内置 WebDriver Manager 自动化机制:只要系统已安装 Chrome 浏览器(Ubuntu 下可通过 sudo apt install chromium-browser 或 google-chrome-stable 安装),Selenium 就能自动匹配并下载对应版本的 ChromeDriver,无需手动下载、解压或配置 PATH。
以下是一个完整、可直接运行的教程级解决方案:
✅ 核心步骤说明
- 启动无头 Chrome(
--headless=true),避免 GUI 开销; - 使用
WebDriverWait等待关键元素加载完成,避免NoSuchElementException; - 定位并模拟点击触发答案展开(本例中需额外补全点击逻辑,原答案未显式调用
.click(),但实际页面需点击才能渲染#accordionExample > ul li); - 解析结构化问答数据,按题干与选项分组输出。
? 补充点击逻辑(关键修正)
原示例代码假设答案已存在 DOM 中,但根据问题描述,答案需点击「Xem đáp án」后才渲染。因此需增加显式点击操作:
立即学习“前端免费学习笔记(深入)”;
from selenium import webdriver
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
from selenium.webdriver.common.by import By
OPTIONS = webdriver.ChromeOptions()
OPTIONS.add_argument("--headless=true")
OPTIONS.add_argument("--no-sandbox")
OPTIONS.add_argument("--disable-dev-shm-usage")
URL = "https://tech12h.com/bai-hoc/trac-nghiem-lich-su-12-bai-1-su-hinh-thanh-trat-tu-gioi-moi-sau-chien-tranh-gioi-thu-hai"
if __name__ == "__main__":
with webdriver.Chrome(options=OPTIONS) as driver:
driver.get(URL)
# 显式等待并点击「Xem đáp án」按钮(根据页面实际 selector 调整)
try:
answer_btn = WebDriverWait(driver, 10).until(
EC.element_to_be_clickable((By.XPATH, "//div[contains(text(), 'Xem đáp án')]"))
)
answer_btn.click()
# 可选:短暂等待动画/渲染完成
WebDriverWait(driver, 5).until(
EC.presence_of_element_located((By.CSS_SELECTOR, "#accordionExample ul li"))
)
except Exception as e:
print("⚠️ 未能定位或点击‘Xem đáp án’按钮,可能已默认展开或 selector 变更:", e)
# 提取题干(<p> 标签)和选项(<li> 标签)
questions = [el.text.strip() for el in driver.find_elements(By.CSS_SELECTOR, "#accordionExample > p")]
answers = [el.text.strip() for el in driver.find_elements(By.CSS_SELECTOR, "#accordionExample > ul li")]
# 每道题含 4 个选项,按 4 分组
for i, q in enumerate(questions):
print(f"{q}")
start, end = i * 4, (i + 1) * 4
for opt in answers[start:end]:
print(f"\t{opt}")⚠️ 注意事项
-
Selector 鲁棒性:网站结构可能更新,建议用浏览器开发者工具(F12)实时验证
#accordionExample > p和//div[contains(text(), 'Xem đáp án')]是否仍准确; -
Ubuntu 兼容性:若报
DevToolsActivePort错误,请确保添加--no-sandbox和--disable-dev-shm-usage参数; - 反爬策略:该站点无强反爬,但生产环境建议添加随机延时、User-Agent 轮换及请求头模拟;
-
替代方案:若因资源限制无法使用 Selenium,可考虑
playwright-python(更轻量、支持多浏览器)或分析网络请求(F12 → Network → XHR/Fetch),直接调用 API 接口(如存在)。
✅ 总结
当网页内容依赖用户交互(点击、悬停、滚动)触发 JavaScript 渲染时,BeautifulSoup 已力不从心;Selenium 是当前最成熟、易上手的解决方案。借助其自动驱动管理、显式等待与元素交互能力,配合合理 CSS/XPath 定位,即可稳定抓取动态问答结构。无需复杂配置,一行 pip install selenium 即可开启可靠自动化采集。
? 提示:首次运行前请确认系统已安装 Chrome/Chromium —— 这是 Selenium 自动化成功的前提。



















