动态加载页面无加载更多按钮,BeautifulSoup无法获取全部元素求助
问题
我尝试抓取页面https://www.doce34.cl/g-shock?order=OrderByNameASC&page=的全部元素,但当前脚本每页仅能获取8个元素,而该页面实际每页显示24个元素。试过多种方法都没解决,求技术帮助。
我的代码
import requests from bs4 import BeautifulSoup as bs import time headers = { "user-agent": "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Ubuntu Chromium/71.0.3578.80 Chrome/71.0.3578.80 Safari/537.36", } filename1 = time.strftime("%Y%m%d") hora=time.strftime("%Y%m%d-%H%M") print (hora) url = "https://www.doce34.cl/g-shock?order=OrderByNameASC&page=" download_delay = 3 for page in range(1,40): req = requests.get(url + str(page)) soup = bs(req.text,'html.parser') contenedor_de_productos = soup.find(class_="vtex-search-result-3-x-gallery flex flex-row flex-wrap items-stretch bn ph1 na4 pl9-l") lista_de_productos = soup.find_all('div', class_='vtex-search-result-3-x-galleryItem vtex-search-result-3-x-galleryItem--normal pa4') contador_producto=1 for producto in lista_de_productos: print("producto numero " + str(contador_producto)) texto_producto=producto.find(class_="vtex-product-summary-2-x-productNameContainer mv0 vtex-product-summary-2-x-nameWrapper overflow-hidden c-on-base f5").text texto_producto=texto_producto.replace('\n', '').replace('\t', '').replace(',', '').replace('"', '').strip() texto_producto_link = producto.find(class_="vtex-product-summary-2-x-container vtex-product-summary-2-x-container--product-summary vtex-product-summary-2-x-containerNormal vtex-product-summary-2-x-containerNormal--product-summary overflow-hidden br3 h-100 w-100 flex flex-column justify-between center tc").a['href'] texto_producto_precio = producto.find(class_="vtex-product-price-1-x-currencyInteger").text contador_producto = contador_producto + 1 print(texto_producto)
问题原因
该网站基于VTEX电商框架开发,产品列表采用动态加载机制。requests.get只能获取页面初始HTML,后续渲染的产品内容不会包含在响应中,因此只能拿到8个初始加载的元素,而非全部24个。
解决方案
方法1:用Selenium模拟浏览器渲染
Selenium会模拟真实浏览器加载页面,等待所有动态内容渲染完成后再抓取数据,能完整获取每页24个元素。
步骤:
- 安装Selenium:
pip install selenium - 下载对应浏览器的驱动(如ChromeDriver,需与浏览器版本匹配)
- 修改代码如下:
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 import time headers = { "user-agent": "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Ubuntu Chromium/71.0.3578.80 Chrome/71.0.3578.80 Safari/537.36", } # 初始化Chrome浏览器(无头模式) options = webdriver.ChromeOptions() options.add_argument(f'user-agent={headers["user-agent"]}') options.add_argument('--headless=new') driver = webdriver.Chrome(options=options) url = "https://www.doce34.cl/g-shock?order=OrderByNameASC&page=" download_delay = 3 for page in range(1, 40): driver.get(url + str(page)) # 等待产品列表加载完成,超时10秒 WebDriverWait(driver, 10).until( EC.presence_of_all_elements_located((By.CLASS_NAME, "vtex-search-result-3-x-galleryItem")) ) # 抓取全部产品元素 lista_de_productos = driver.find_elements(By.CLASS_NAME, "vtex-search-result-3-x-galleryItem") contador_producto = 1 for producto in lista_de_productos: print(f"producto numero {contador_producto}") # 提取产品名称 texto_producto = producto.find_element(By.CLASS_NAME, "vtex-product-summary-2-x-productNameContainer").text texto_producto = texto_producto.replace('\n', '').replace('\t', '').replace(',', '').replace('"', '').strip() # 提取产品链接 texto_producto_link = producto.find_element(By.CLASS_NAME, "vtex-product-summary-2-x-container").find_element(By.TAG_NAME, "a").get_attribute('href') # 提取产品价格 texto_producto_precio = producto.find_element(By.CLASS_NAME, "vtex-product-price-1-x-currencyInteger").text contador_producto += 1 print(texto_producto) time.sleep(download_delay) driver.quit()
方法2:直接调用API接口(更高效)
通过浏览器开发者工具(F12)抓包,找到网站获取产品列表的API接口,直接请求接口获取结构化JSON数据,无需解析HTML。
示例代码(需自行抓包确认准确接口地址):
import requests import time headers = { "user-agent": "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Ubuntu Chromium/71.0.3578.80 Chrome/71.0.3578.80 Safari/537.36", "accept": "application/json" } # 示例API地址,需自行抓包验证 api_url = "https://www.doce34.cl/api/catalog_system/pub/products/search?fq=C:/1/&order=OrderByNameASC&page=" download_delay = 3 for page in range(1, 40): req = requests.get(api_url + str(page), headers=headers) products = req.json() contador_producto = 1 for producto in products: print(f"producto numero {contador_producto}") texto_producto = producto['productName'].replace('\n', '').replace('\t', '').replace(',', '').replace('"', '').strip() texto_producto_link = f"https://www.doce34.cl{producto['link']}" texto_producto_precio = producto['items'][0]['sellers'][0]['commertialOffer']['Price'] contador_producto += 1 print(texto_producto) time.sleep(download_delay)
内容的提问来源于stack exchange,提问作者Marioloteitor
相关产品推荐
相关产品推荐

