使用Beautiful Soup+Selenium爬取动态内容时源码与实际内容不符
问题分析与解决方案
为什么获取的页面源码没有实际显示元素?
核心原因主要有两个:
- 固定时间等待不可靠:你用
time.sleep(10)来等待页面加载,但动态网站的渲染速度受网络、服务器响应等因素影响很大——10秒可能在某些场景下足够,但如果网站加载慢,或者需要触发滚动/交互才加载内容,此时DOM里还没渲染出目标元素,page_source自然只有初始的HTML和JS代码。 - 未针对目标元素做显式等待:Selenium的
page_source获取的是调用时刻的DOM状态,如果你没确保目标元素已经完全渲染就调用它,得到的必然是未加载完成的页面内容。
除了获取页面源码,还有哪些更可靠的方法?
这里推荐几种适配动态网站的方案:
1. 用显式等待确保元素加载后再获取源码
把time.sleep(10)替换成WebDriverWait,针对你要抓取的目标元素做显式等待,确保它已经出现在DOM中。比如假设网站的游戏条目是带有release-item类的元素,修改后的代码如下:
from bs4 import BeautifulSoup as soup from selenium.webdriver.support.ui import WebDriverWait from selenium.webdriver.support import expected_conditions as EC from selenium.webdriver.common.by import By from selenium import webdriver import chromedriver_binary # constants my_url = "https://www.releases.com/l/Games/2018/1/" # Start the WebDriver and load the page wd = webdriver.Chrome() wd.get(my_url) try: # 显式等待目标元素出现(最多等待20秒),替换成你实际要抓取的元素定位器 WebDriverWait(wd, 20).until( EC.presence_of_element_located((By.CSS_SELECTOR, ".release-item")) ) # 如果是滚动加载网站,可模拟滚动到底部加载更多内容 # wd.execute_script("window.scrollTo(0, document.body.scrollHeight);") # time.sleep(2) # 给滚动后的内容留加载时间 except Exception as e: print(f"等待元素加载失败: {e}") # 现在再获取完整渲染后的页面源码 html_page = wd.page_source wd.quit() # Parse and extract data pageSoup = soup(html_page, "html.parser") print(pageSoup.text)
2. 直接用Selenium定位元素提取数据,无需BeautifulSoup
既然已经用了Selenium,完全可以跳过获取源码这一步,直接用它的元素定位方法抓取数据,这样更高效:
from selenium.webdriver.support.ui import WebDriverWait from selenium.webdriver.support import expected_conditions as EC from selenium.webdriver.common.by import By from selenium import webdriver import chromedriver_binary my_url = "https://www.releases.com/l/Games/2018/1/" wd = webdriver.Chrome() wd.get(my_url) try: # 等待所有游戏条目加载完成 WebDriverWait(wd, 20).until( EC.presence_of_all_elements_located((By.CSS_SELECTOR, ".release-item")) ) # 遍历所有游戏条目提取信息 game_items = wd.find_elements(By.CSS_SELECTOR, ".release-item") for item in game_items: title = item.find_element(By.TAG_NAME, "h3").text release_date = item.find_element(By.CSS_SELECTOR, ".date").text print(f"游戏名称: {title}, 发布日期: {release_date}") except Exception as e: print(f"抓取数据失败: {e}") finally: wd.quit()
3. 执行JavaScript获取完整渲染后的DOM
有时候page_source可能会漏掉部分动态渲染内容,你可以通过执行JS来获取整个页面的完整HTML:
html_page = wd.execute_script("return document.documentElement.outerHTML;")
额外提示
如果网站是滚动加载(下滑才加载更多内容),你需要循环执行滚动操作并等待加载,直到没有新内容出现为止,才能抓取到全部数据。
内容的提问来源于stack exchange,提问作者Morrywinn
相关产品推荐
相关产品推荐

