如何使用BeautifulSoup处理点击div标签后才加载的HTML内容以抓取试题答案?
如何使用BeautifulSoup处理点击div标签后才加载的HTML内容以抓取试题答案?
嘿,我来帮你梳理下这个问题的解决思路哈!首先得明确:BeautifulSoup本身是处理静态HTML的工具,它只能解析你首次请求网页时返回的源码,但你说的点击「Xem đáp án」div后才显示的答案,是通过JavaScript动态加载的——这部分内容在初始页面源码里根本不存在,所以直接用BeautifulSoup肯定抓不到。
那该怎么办呢?给你两个可行的方案,你可以根据自己的情况选:
方案一:解决Selenium的驱动冲突,模拟浏览器点击获取动态内容
你在Ubuntu上遇到的Selenium驱动冲突,大多是因为Chrome浏览器和ChromeDriver版本不匹配,或者启动参数没设置对。我给你一步步说怎么解决:
- 先确认Chrome版本:打开终端输入
google-chrome --version,记下来版本号(比如Google Chrome 125.0.6422.112)。 - 匹配对应版本的ChromeDriver:
- 如果你用的是Chromium,可以直接用包管理器安装:
sudo apt install chromium-chromedriver,但要确保安装的驱动版本和浏览器版本一致。 - 如果是官方Chrome,下载对应大版本的驱动,解压后把驱动文件放到
/usr/local/bin或者添加到系统PATH里。
- 如果你用的是Chromium,可以直接用包管理器安装:
- 修改Selenium启动参数:Ubuntu环境下要加上几个参数避免权限和资源问题,然后模拟点击操作,再用BeautifulSoup解析最终的页面源码。
给你个示例代码,你可以根据目标页面的实际元素调整定位方式:
from selenium import webdriver from selenium.webdriver.common.by import By from selenium.webdriver.support.ui import WebDriverWait from selenium.webdriver.support import expected_conditions as EC from bs4 import BeautifulSoup # 配置Chrome启动选项,适配Ubuntu环境 chrome_options = webdriver.ChromeOptions() chrome_options.add_argument('--headless=new') # 无头模式,不用弹出浏览器窗口 chrome_options.add_argument('--no-sandbox') # 绕过沙箱限制,Ubuntu环境必备 chrome_options.add_argument('--disable-dev-shm-usage') # 解决/dev/shm内存不足的问题 # 初始化驱动,如果驱动不在PATH里,可指定executable_path参数 driver = webdriver.Chrome(options=chrome_options) try: # 打开目标网页 target_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" driver.get(target_url) # 等待「Xem đáp án」按钮加载完成并点击 # 这里用XPath定位,你也可以根据按钮的class属性调整 wait = WebDriverWait(driver, 10) answer_btn = wait.until(EC.element_to_be_clickable( (By.XPATH, "//div[contains(text(), 'Xem đáp án')]") )) answer_btn.click() # 等待答案内容加载出来 wait.until(EC.presence_of_element_located((By.CLASS_NAME, "answer-item"))) # 替换成实际答案容器的class # 获取加载完成后的页面源码,交给BeautifulSoup解析 page_html = driver.page_source soup = BeautifulSoup(page_html, 'html.parser') # 提取答案内容,根据实际页面结构调整选择器 answers = soup.find_all("div", class_="answer-item") for idx, ans in enumerate(answers, 1): print(f"第{idx}题答案:{ans.get_text(strip=True)}") finally: # 不管成功失败,都要关闭浏览器驱动 driver.quit()
方案二:直接抓取动态加载的接口(更高效)
其实很多网站点击按钮加载内容时,会发送一个AJAX请求到后端接口获取数据,这种方式比模拟浏览器更高效,还能避免驱动问题。你可以这么做:
- 打开浏览器的开发者工具(F12),切换到「Network」标签,勾选「XHR」选项。
- 点击页面上的「Xem đáp án」按钮,观察Network面板里新出现的请求,找到返回答案数据的接口。
- 复制这个接口的URL、请求方法(GET/POST)和请求头,用
requests库直接发送请求,就能拿到答案的JSON数据,不用再处理HTML了。
举个简单的示例(假设接口是GET请求):
import requests headers = { "User-Agent": "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/125.0.0.0 Safari/537.36" } # 替换成你找到的实际接口URL api_url = "https://tech12h.com/api/get-answers?id=xxx" response = requests.get(api_url, headers=headers) answer_data = response.json() # 解析JSON数据提取答案 for item in answer_data['data']: print(f"题目{item['question_id']}答案:{item['answer']}")
这个方法的关键是找到正确的接口,你可以看接口的请求参数,比如有没有携带页面的ID之类的,这些参数通常能在初始页面的源码里找到。
备注:内容来源于stack exchange,提问作者Dinosaur
相关产品推荐
相关产品推荐

