Solucionado (ver solução)
Solucionado
(ver solução)
1
resposta

Não consigo pegar a tabela do site.

Estou desenvolvendo um projeto para trinar minhas habilidades com Web Scraping, mas não estou conseguindo acessar os dados da tabela de um site. Quero poder pegar esta tabela e formar uma lista com dicionários e depois armazenar esses dados em um arquivo Json. Segue o código:

# imports
from urllib.request import urlopen, urlretrieve
from urllib.error import URLError, HTTPError

from bs4 import BeautifulSoup

import pandas as pd

from selenium import webdriver
from selenium.webdriver.chrome.service import Service
from selenium.webdriver.common.by import By
from selenium.webdriver.common.keys import Keys
from selenium.webdriver.chrome.options import Options

import requests

import json

from time import sleep

# Definindo o caminho do PATH
PATH = "C:\Program Files (x86)\chromedriver.exe"
driver = webdriver.Chrome(PATH)
#Definindo a URL
url = "https://www.fundamentus.com.br/resultado.php"
# Acessando a url
page = driver.get(url)
# Dando um tempo para o navegador carregar e conseguir raspar o elemento
sleep(10)


page_content = requests.get(url).text
# Parsear o contúdo HTML - bs4
soup = BeautifulSoup(page_content, 'html.parser')
tables = soup.find_all("table")
# Criando um lista para inserir os dicts
table = []


tab_data = [[cell.text for cell in row.find_all(["th","td"])]for row in table.find_all("tr")]
# Estruturar os Dados em um DataFrame - pandas
df = pd.DataFrame(tab_data)


# Transformar os Dados em um dicionário de dados próprios
# Converter e salvar em um arquivo Json

# Saindo do Navegador
driver.quit()

Tentei fazer o WS sem o selenium, porém acho que o site carrega dinamicamente então não consegui usar somente o BeautifulSoup. Ao tentar fazer o WS somente com o bs4 recebo no print, uma url = http://www.w3.org/TR/html4/strict.dtd .

1 resposta
solução!

Boa noite Maurício...

Gostei do seu problema e tentei resolvê-lo aqui pra me desafiar.

E não é que consegui!!! Mas usando apenas o BeautifulSoup. O legal é que o script demora apenas 1 min pra rodar.... Gostei demais!

Bom, pelo menos eu consegui a primeira parte, né... A de pegar os dados da tabela lá do site.

A segunda parte de passar pra json, deixo pra vc pq eu não sei... hahahah

Segue o código...

%%time

# Imports
from bs4 import BeautifulSoup
import pandas as pd
from urllib.request import Request, urlopen
from urllib.error import URLError, HTTPError

# Definindo características da página
url = 'https://www.fundamentus.com.br/resultado.php'
headers = {'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/76.0.3809.100 Safari/537.36'}

# Fazendo a request
try:
    req = Request(url, headers = headers)
    response = urlopen(req)
    print('Foi\n\n')
    print(response.getcode())
    html = response.read()

# Tratando alguns possíveis erros
except HTTPError as e:
    print('HTTPError\n\n')
    print(response.getcode())
    print(e.status, e.reason)

except URLError as e:
    print('URLError\n\n')
    print(response.getcode())
    print(e.reason)

# Instanciando um objeto BeautifulSoup
soup = BeautifulSoup(html, 'html.parser')

# Pegando os nomes das colunas da tabela
colunas_names = [col.getText() for col in soup.find('table', {'id': 'resultado'}).find('thead').findAll('th')]
colunas = {i: col.getText() for i, col in enumerate(soup.find('table', {'id': 'resultado'}).find('thead').findAll('th'))}

# Criando um DataFrame com os nomes das colunas
dados = pd.DataFrame(columns=colunas_names)

# Pegando os dados da tabela por linha
for i in range(len(soup.find('table', {'id': 'resultado'}).find('tbody').findAll('tr'))):
    linha = soup.find('table', {'id': 'resultado'}).find('tbody').findAll('tr')[i].getText().split('\n')[1:]
    inserir_linha = pd.DataFrame(linha).T.rename(columns=colunas)
    dados = pd.concat([dados, inserir_linha], ignore_index=True)

# É tetra!
dados