在for循环中的Bs4 find方法不解析所有标记,只解析第一个标记

2024-10-01 04:58:53 发布

您现在位置:Python中文网/ 问答频道 /正文

我试图解析iphone的数据。这段代码几乎可以正常工作,但它只检索每个页面中第一部iphone的数据。我试着研究其他几个话题,但没能解决我的问题。该问题与下面的代码一起处理

代码如下:

from bs4 import BeautifulSoup
import pandas as pd
import time as tm
from selenium import webdriver


path = "isert your driver path here"

termo_busca = 'iphone'
url = f'https://www.magazineluiza.com.br/busca/{termo_busca}/'

#im using selenium browser acces the website and 
#then parse  the html with bs4 cause the website reconized both
#requests_html and urllib requests as bots.

#this function parse the html

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

find_all方法正在解析我想要的所有信息,但是for循环中的find方法只解析每个页面的第一组元素。怎么了

lista_dados = []


def extrator_dados(soup):
    
links = soup.find_all('section', {'style' : 'grid-area:content'}) #pega o link e o nome produto
    
    preco_normal = 0
    preco_promocao_avista = 0
    preco_promocao_parcelado = 0
    num_avaliacoes = 0

    for item in links:
        nome_produto = item.find('h2', {'class': 'sc-bHXGc hsFKpx'}).text.strip()
        link_produto = 'https://www.magazineluiza.com.br' + str(item.find('a', {'class': 'sc-kfzBvY kHKKYz sc-kNMMVl fJHpec'})['href'])   
      
        try:   
            preco_normal = item.find('p', {'class' : 'sc-hKgJUU eKvUCv sc-jYCGPb kAAMBY'}).text.replace('R$','').strip()
            preco_promocao_avista = item.find('p', {'class': 'sc-hKgJUU kegCEa sc-bxnjHY cTpdOW'}).text.replace('R$','').strip()
            preco_promocao_parcelado = item.find('p', {'class': 'sc-hKgJUU nIoWN sc-gyUflj dQzJJE'}).text.replace('R$','').strip() #.replace('ou', '').replace('x de', '').replace('sem juros', '')

        except:
            preco_normal = 0
            preco_promocao_avista = 0    
            preco_promocao_parcelado = 0 

        try:
            num_avaliacoes = item.find('span', {'class': 'sc-irOPex eZnwGI'}).text.strip()

        except:

            num_avaliacoes = 0
            #numero_avaliacoes = [item.get_text(strip = True) for item in links3.find('span', {'class': 'sc-irOPex eZnwGI'})]
   
        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

另一个问题是代码没有提取下面标记中的文本元素(评论的数量),即使find_all&;上面使用的find方法正在正确解析它

num_avaliacoes=item.find('span',{'class':'sc-irOPex-eZnwGI'}).text.strip()


#loop through the 17 pages of the website with iphone's data

for url2 in range(1,17):
    url2 = f'https://www.magazineluiza.com.br/busca/iphone/?page={url2}'    
    soup = extrator_html_selenium(url2)
    extrator_dados(soup)
    print(len(lista_dados))


#create a df with the parsed data

df = pd.DataFrame(lista_dados)
df.to_csv('iphones_magalu_final.csv', index=False)


提前谢谢你


Tags: thetexthtmlfinditemnumclassstrip
1条回答
网友
1楼 · 发布于 2024-10-01 04:58:53

发生了什么事?

您正在选择外部容器,它保存您想要迭代的项目find_all()在本例中,它将为您提供一个包含一个元素的列表,这就是您仅获取第一项的原因

如何修复?

这很简单-用data-testid="productlist"选择<div>中的所有<li>,它就会工作。更改为:

links = soup.find_all('section', {'style' : 'grid-area:content'})

致:

links = soup.select('div[data-testid="product-list"] li')

输出

    nome_produto    link_produto    preco_normal    preco_promocao_avista   preco_promocao_parcelado    num_avaliacoes
0   iPhone 11 Apple 64GB Roxo 6,1” 12MP iOS https://www.magazineluiza.com.br/iphone-11-app...   5.699,00    3.999,00    ou 10x de  399,90 sem juros 1
1   iPhone 11 Apple 64GB Preto 6,1” 12MP iOS    https://www.magazineluiza.com.br/iphone-11-app...   5.699,00    3.999,00    ou 10x de  399,90 sem juros 80
2   iPhone XR Apple 64GB Preto 6,1” 12MP iOS    https://www.magazineluiza.com.br/iphone-xr-app...   4.999,00    3.399,00    ou 10x de  339,90 sem juros 88

提示

该站点使用机器人检测,因此在刮取时要加以限制(;)

相关问题 更多 >