BeautifulSoup两大技术问题:find_all返回空列表及如何遍历动态加载容器内容
解决BeautifulSoup返回空列表及动态内容遍历问题
一、为什么BeautifulSoup返回空列表?
你遇到的核心问题是页面内容是JavaScript动态渲染的——用requests.get()只能拿到网站的初始HTML源码,而目标的mobmenu-push-wrap类对应的div,是页面加载完成后通过JS动态生成的,初始源码里根本没有这部分内容,所以不管换哪种解析器,find_all都找不到匹配元素,自然返回空列表。
你可以自己验证下:把response.text打印出来,搜索mobmenu-push-wrap,肯定搜不到相关内容。
给你两个可行的解决思路:
- 思路1:抓接口直接拿数据
打开网站按F12进入开发者工具的Network面板,刷新页面后看XHR标签下的请求,找返回供应商数据的接口(一般是JSON格式),直接请求这个接口获取数据,比解析HTML效率高得多。 - 思路2:用自动化工具模拟浏览器加载
用Selenium或Playwright这类工具模拟真实浏览器打开页面,等JS渲染完成后再提取HTML。给你个Selenium的简单示例:
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 from bs4 import BeautifulSoup url = "https://betonabq.org/les-membres/membres-producteurs-v2/" driver = webdriver.Chrome() # 需提前安装对应版本的ChromeDriver driver.get(url) # 等待目标元素加载完成 WebDriverWait(driver, 10).until( EC.presence_of_element_located((By.CLASS_NAME, "mobmenu-push-wrap")) ) # 获取渲染后的完整HTML html = driver.page_source html_soup = BeautifulSoup(html, 'lxml') beton_containers = html_soup.find_all('div', class_='mobmenu-push-wrap') # 处理完记得关闭浏览器 driver.quit()
二、如何遍历点击后加载的Div内容?
这类点击后才动态加载的内容,同样没法用静态请求获取,必须用自动化工具模拟用户交互流程。以Selenium为例,大致步骤如下:
- 初始化浏览器并打开目标页面,等待左侧供应商列表加载完成;
- 定位所有左侧供应商列表项(需要通过开发者工具找对应的CSS选择器或class);
- 逐个点击列表项,每次点击后等待详情Div加载完成;
- 提取详情Div里的信息,重复操作直到遍历完所有供应商。
简单示例代码参考:
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 url = "https://betonabq.org/les-membres/membres-producteurs-v2/" driver = webdriver.Chrome() driver.get(url) wait = WebDriverWait(driver, 10) # 替换成左侧供应商列表的真实选择器,比如通过class定位 supplier_items = wait.until( EC.presence_of_all_elements_located((By.CLASS_NAME, "左侧列表项的class")) ) for item in supplier_items: # 若直接点击无效,可改用JS点击:driver.execute_script("arguments[0].click();", item) item.click() # 等待详情Div加载,替换成真实的class或选择器 detail_div = wait.until( EC.presence_of_element_located((By.CLASS_NAME, "详情Div的class")) ) # 提取信息,比如文本内容或子元素数据 supplier_info = detail_div.text print(supplier_info) driver.quit()
注意:你需要自己通过浏览器开发者工具,找到左侧列表项和详情Div的正确选择器(class、id或CSS路径),如果点击时遇到元素遮挡,改用JS点击的方式会更稳定。
内容的提问来源于stack exchange,提问作者Noah Khounsombath
相关产品推荐
相关产品推荐

