如何串联Selenium展开逻辑与BeautifulSoup实现网页全量数据爬取
问题本质
两段代码无法衔接的核心原因是:原有爬取逻辑通过urllib.urlopen(url)发起了一次全新的、没有任何用户交互的网络请求,拿到的是服务器直接返回的初始未展开的静态HTML,完全没有用到之前Selenium浏览器里点击Expand All之后、动态渲染完成的页面内容,自然获取不到隐藏的字段。
核心解决思路
不需要用urllib二次请求页面,直接从已经完成展开操作的Selenium浏览器实例里,把当前渲染好的全量页面源码抓出来,传给BeautifulSoup解析,就能把两段逻辑接成完整流程。
分步改造步骤
- 保留现有Selenium的全部逻辑:初始化浏览器、遍历股票代码、打开目标金融页面、定位点击Expand All按钮完成字段展开。
- 点击完展开按钮之后,等页面渲染完成,直接用Selenium的内置接口
driver.page_source拿到当前页面的完整HTML,替代原来的urllib请求步骤。 - 把拿到的HTML字符串作为入参传给BeautifulSoup,后续的字段筛选、列表生成逻辑可以完全复用原有代码,不需要大改。
原有代码的常见坑点
- 语法坑:原代码里的
soup_is.find_all("div" and "span")有Python短路求值的问题,"div" and "span"的运算结果就是返回后一个字符串"span",相当于你从来没匹配过div标签,这也是之前数据不全的可能原因。如果要同时匹配div和span,正确写法是find_all(["div", "span"])。 - 版本适配:Selenium 4.0以上版本,初始化Chrome驱动时,原来的
chrome_options=options参数已经被弃用,要改成options=options,不然会报警告甚至运行报错。 - 渲染延迟:点击Expand All之后不要立刻抓页面源码,等个1-2秒或者用显式等待确认所有展开元素加载完成再抓,不然可能因为页面还没渲染完拿到残缺的内容。
整合后可直接运行的参考实现
from selenium import webdriver from selenium.webdriver.chrome.options import Options from selenium.webdriver.support.ui import WebDriverWait from selenium.webdriver.common.by import By from selenium.webdriver.support import expected_conditions as EC from bs4 import BeautifulSoup import time # 初始化浏览器配置 options = Options() options.add_argument("start-maximized") # 替换为本机chromedriver的实际安装路径 driver = webdriver.Chrome(options=options, executable_path='C:\\Program Files\\chromedriver.exe') # 配置需要爬取的股票代码列表 ticker_list = ["MSFT"] for ticker in ticker_list: url = "https://finance.yahoo.com/quote/{}/financials?p={}".format(ticker, ticker) driver.get(url) # 等待Expand All按钮可点击,完成展开操作 expand_btn = WebDriverWait(driver, 30).until( EC.element_to_be_clickable((By.XPATH, "//section[@data-test='qsp-financial']//span[text()='Expand All']")) ) expand_btn.click() # 等待展开的动态元素渲染完成 time.sleep(2) # 直接获取当前浏览器渲染完成的全量页面HTML,不再发起新的网络请求 rendered_page = driver.page_source # 用BeautifulSoup解析渲染后的页面 soup = BeautifulSoup(rendered_page, "lxml") data_list = [] # 修正标签匹配逻辑,同时抓取div和span标签的内容 for item in soup.find_all(["div", "span"]): data_list.append(item.string) # 过滤不需要的固定文本和空值 data_list = [item for item in data_list if item not in ("Operating Expenses", "Non-recurring Events", None)] # 后续可直接把data_list转成pandas DataFrame做处理 print(data_list) # 全部任务完成后关闭浏览器释放资源 driver.quit()
代码中的等待时长、chromedriver路径需要根据本机实际环境、目标网站加载速度调整。
内容的提问来源于stack exchange,提问作者pythonNovice
相关产品推荐
相关产品推荐

