Bs4 for循环内find方法仅解析首个标签 评论数提取失败求助
问题定位与修复方案
故障1:每页仅返回第一个商品
- 核心错误:
soup.find_all('section', {'style' : 'grid-area:content'})匹配的是整个商品列表的父容器,每页仅存在1个该节点,因此for循环仅执行1次,只能提取到第一个商品的信息。 - 附带语法问题:原代码中
extrator_dados函数下的links定义行缩进错误,会直接触发语法异常。
故障2:评论数无法正确提取
- 你使用的是React框架生成的动态类名,类名的随机后缀会随站点部署更新,完整匹配类名会不定期失效;同时部分无评论的商品本身不存在该标签,需要做兼容匹配。
修复后可运行代码
from bs4 import BeautifulSoup import pandas as pd import time as tm from selenium import webdriver # 替换为你的ChromeDriver路径 path = "insert your driver path here" termo_busca = 'iphone' lista_dados = [] def extrator_html_selenium(url): navegador = webdriver.Chrome(path) navegador.get(url) tm.sleep(5) html = navegador.page_source soup = BeautifulSoup(html, 'html5lib') navegador.quit() return soup def extrator_dados(soup): # 先定位商品列表父容器,再匹配所有单个商品节点 content_section = soup.find('section', {'style' : 'grid-area:content'}) # 匹配所有商品项,用类名前缀匹配避免动态后缀影响 items = content_section.find_all('li', class_=lambda x: x and x.startswith('sc-')) for item in items: preco_normal = 0 preco_promocao_avista = 0 preco_promocao_parcelado = 0 num_avaliacoes = 0 try: nome_produto = item.find('h2', class_=lambda x: x and 'sc-bHXGc' in x).text.strip() link_produto = 'https://www.magazineluiza.com.br' + str(item.find('a', class_=lambda x: x and 'sc-kfzBvY' in x)['href']) except: # 跳过无效商品节点 continue try: preco_normal = item.find('p', class_=lambda x: x and 'sc-hKgJUU eKvUCv' in x).text.replace('R$','').strip() preco_promocao_avista = item.find('p', class_=lambda x: x and 'sc-hKgJUU kegCEa' in x).text.replace('R$','').strip() preco_promocao_parcelado = item.find('p', class_=lambda x: x and 'sc-hKgJUU nIoWN' in x).text.replace('R$','').strip() except: pass try: # 用类名前缀匹配评论数标签,避免动态后缀影响 num_avaliacoes = item.find('span', class_=lambda x: x and 'sc-irOPex' in x).text.strip() except: pass dados_dict = { 'nome_produto' : nome_produto, 'link_produto' : link_produto, 'preco_normal' : preco_normal, 'preco_promocao_avista' : preco_promocao_avista, 'preco_promocao_parcelado': preco_promocao_parcelado, 'num_avaliacoes': num_avaliacoes } lista_dados.append(dados_dict) return # 遍历17页数据 for page in range(1,17): page_url = f'https://www.magazineluiza.com.br/busca/iphone/?page={page}' soup = extrator_html_selenium(page_url) extrator_dados(soup) print(f"已爬取{len(lista_dados)}条数据") # 导出CSV df = pd.DataFrame(lista_dados) df.to_csv('iphones_magalu_final.csv', index=False)
额外优化建议
- 可以把固定等待
tm.sleep(5)替换为Selenium的显式等待,等待商品列表加载完成再提取数据,既提升效率也避免网络波动导致的加载不全问题。 - 动态类名如果后续失效,可以改为按节点层级定位,不要依赖类名匹配,稳定性更高。
内容的提问来源于stack exchange,提问作者Gabs
相关产品推荐
相关产品推荐

