tl;dr
Eu não usaria Selenium para este caso, pois existem libs mais adequadas para web scraping. Em todo caso, seguem algumas soluções (com e sem Selenium).
Selenium
Se a ideia é continuar com Selenium, existem várias formas de iterar pelas linhas da string. Por exemplo, criando um iterador, e chamando next
para obter a próxima linha:
texto_produtos = produtos.text
linhas = iter(texto_produtos.split("\n"))
result = []
while True:
try:
result.append( { "Nome": next(linhas), "Preco": next(linhas), "Carrinho": next(linhas), "Lista": next(linhas) } )
except StopIteration:
break
print(result)
Assim, cada chamada de next
traz a próxima linha, e aí basta colocá-las no dicionário, e adicioná-lo na lista. O chato é que quando um iterador se encerra, ele lança um StopIteration
, que precisa ser capturado, e aí sabemos que o loop pode ser interrompido (com break
).
No módulo itertools
existe também uma "receita pronta" para iterar qualquer sequência de N em N elementos:
texto_produtos = produtos.text
from itertools import zip_longest
def grouper(iterable, n, fillvalue=None):
args = [iter(iterable)] * n
return zip_longest(*args, fillvalue=fillvalue)
result = []
for nome, preco, carrinho, lista in grouper(texto_produtos.split("\n"), 4):
result.append( { "Nome": nome, "Preco": preco, "Carrinho": carrinho, "Lista": lista } )
print(result)
Agora não preciso capturar o StopIteration
, e repare que no for
já posso pegar cada um dos 4 elementos separadamente.
E também posso usar list comprehension para obter o mesmo resultado:
texto_produtos = produtos.text
from itertools import zip_longest
def grouper(iterable, n, fillvalue=None):
args = [iter(iterable)] * n
return zip_longest(*args, fillvalue=fillvalue)
result = [ { "Nome": nome, "Preco": preco, "Carrinho": carrinho, "Lista": lista } for nome, preco, carrinho, lista in grouper(texto_produtos.split("\n"), 4)]
print(result)
Por fim, também pode ser usado o código sugerido no outro comentário:
texto_produtos = produtos.text
lista_produtos = texto_produtos.split("\n")
result = []
for i in range(0, len(lista_produtos), 4):
nome, preco, carrinho, lista = lista_produtos[i:i + 4]
result.append( { "Nome": nome, "Preco": preco, "Carrinho": carrinho, "Lista": lista } )
print(result)
Sem Selenium
Como eu já disse, nesse caso não precisa de Selenium, existem bibliotecas mais apropriadas para web scraping. Vamos ver uma delas: o Beautiful Soup.
Mas antes um detalhe: repare que você está preenchendo o campo de busca e mudando o filtro para "mais recentes". Ao fazer isso, a URL resultante é https://panini.com.br/catalogsearch/result?q=Universo+Sandman&product_list_order=most_recent
, então você pode acessá-la diretamente, em vez de dar toda essa volta de abrir o browser, digitar, esperar o resultado, etc...
Beautiful Soup
Primeiro, aqui tem a documentação e instruções de instalação (python -m pip install beautifulsoup4
).
Depois, instale também o módulo requests
(python -m pip install requests
) para fazer a requisição HTTP e obter o HTML. Assim é mais direto do que abrir o browser com o Selenium, pois só o que interessa é o conteúdo do HTML (vc pode usar outros também, existem várias libs para fazer requests HTTP, o importante é que no final vc tenha o HTML para repassar para o Beautiful Soup).
from bs4 import BeautifulSoup
from urllib.request import urlopen
url = 'https://panini.com.br/catalogsearch/result?q=Universo+Sandman&product_list_order=most_recent'
soup = BeautifulSoup(urlopen(url).read().decode("utf-8"), "html.parser")
lista_produtos = list(filter(lambda s : len(s.strip()) > 0 and s != 'Adicionar para Comparar',
soup.find('div', {'class': 'products-grid'}).get_text(separator='\n').split('\n')))
Mas repare que o Beautiful Soup trata um pouco diferente o conteúdo, tanto que o texto vem com muitos espaços e quebras de linha a mais, além de trazer também o texto "Adicionar para Comparar". Então precisei fazer um tratamento adicional para ter uma lista igual a que você obtém com o Selenium.
Depois disso, é só escolher um dos métodos acima para ler a lista de 4 em 4 elementos.
Outra opção é, em vez de pegar todo o texto, simplesmente buscar cada elemento que você quer. Dá um pouco mais de trabalho e precisa fuçar a estrutura da página, mas não tem jeito. Pelo menos você vai direto no elemento que tem a informação:
from bs4 import BeautifulSoup
from urllib.request import urlopen
url = 'https://panini.com.br/catalogsearch/result?q=Universo+Sandman&product_list_order=most_recent'
soup = BeautifulSoup(urlopen(url).read().decode("utf-8"), "html.parser")
result = []
for product in soup.find_all('div', {'class': 'product-item-details'}):
nome = product.find('a', {'class': 'product-item-link'}).text
if not nome:
continue
preco = product.find('span', {'class': 'price'}).text
carrinho = product.find('button', {'class': 'tocart'})
if carrinho is None:
carrinho = product.find('div', {'class': 'unavailable'}).text
else:
carrinho = carrinho.text
lista = product.find('a', {'class': 'towishlist'}).find('span').text
result.append( { "Nome": nome, "Preco": preco, "Carrinho": carrinho, "Lista": lista } )
print(result)
Outras opções
Existem várias bibliotecas para web scraping, como o Scrapy, entre outras. Sugiro testá-las para ver como são, mas nesse caso específico, Selenium não me parece a melhor opção. Não há necessidade de abrir um browser, buscar, clicar em tal elemento, quando você pode obter o HTML acessando a URL diretamente (na página que vc acessa, não precisa ficar rodando JavaScript para que certos elementos apareçam, etc, situação na qual o Selenium é mais apropriado).