Exemple #1
0
def __busca_etfs_na_b3():
    try:
        url = 'http://bvmf.bmfbovespa.com.br/etf/fundo-de-indice.aspx?idioma=pt-br&aba=tabETFsRendaVariavel'
        driver = ChromeDriver()
        driver.get(url)

        etfs = __converte_etfs_para_dataframe(driver)
        return set(etfs['Código'])
    except:
        return set()
Exemple #2
0
 def __init__(self, headless=False, directory=None, debug=False):
     self.BASE_URL = 'https://ceiapp.b3.com.br/CEI_Responsivo/'
     self.driver = ChromeDriver()
     self.directory = directory
     self.debug = debug
     self.__colunas_df_cei = [
         'Data do Negócio', 'Compra/Venda', 'Mercado', 'Prazo/Vencimento',
         'Código Negociação', 'Especificação do Ativo', 'Quantidade',
         'Preço (R$)', 'Valor Total(R$)', 'Fator de Cotação'
     ]
     self.id_tabela_negociacao_ativos = 'ctl00_ContentPlaceHolder1_rptAgenteBolsa_ctl00_rptContaBolsa_ctl00_pnAtivosNegociados'
     self.id_mensagem_de_aviso = 'CEIMessageDIV'
     self.id_selecao_corretoras = 'ctl00_ContentPlaceHolder1_ddlAgentes'
     self.id_btn_consultar = 'ctl00_ContentPlaceHolder1_btnConsultar'
Exemple #3
0
def get_random_opcoes_tickers():
    driver = None
    driver = ChromeDriver()
    driver.get('https://opcoes.net.br/opcoes/bovespa/PETR4')

    WebDriverWait(driver, 10).until(
        EC.visibility_of_element_located((By.ID, 'tblListaOpc')))

    soup = BeautifulSoup(driver.page_source, 'html.parser')

    table = soup.find('table', {'id': 'tblListaOpc'})

    df = pd.read_html(str(table), decimal=',', thousands='.')[0]

    return df['Ticker']['Ticker'].tolist()
Exemple #4
0
 def __init__(self, headless=False, directory='./temp/', debug=False):
     self.BASE_URL = 'https://ceiapp.b3.com.br/CEI_Responsivo/'
     self.driver = ChromeDriver()
     self.directory = directory
     self.debug = debug
     self.__colunas_df_cei = ['Data do Negócio', 'Compra/Venda', 'Mercado', 'Prazo/Vencimento', 'Código Negociação',
            'Especificação do Ativo', 'Quantidade', 'Preço (R$)', 'Valor Total(R$)', 'Fator de Cotação']
     self.__colunas_df_carteira = ['Empresa', 'Tipo', 'ticker', 'isin', 'Preço (R$)',
            'Quantidade', 'Fator de Cotação' 'Valor Total(R$)']
     self.id_tabela_negociacao_ativos = 'ctl00_ContentPlaceHolder1_rptAgenteBolsa_ctl00_rptContaBolsa_ctl00_pnAtivosNegociados'
     self.id_mensagem_de_aviso = 'CEIMessageDIV'
     self.id_selecao_corretoras = 'ctl00_ContentPlaceHolder1_ddlAgentes'
     self.id_btn_consultar = 'ctl00_ContentPlaceHolder1_btnConsultar'
     self.id_selecao_data = 'ctl00_ContentPlaceHolder1_txtData'
     self.agentes_ignorar = {}
     if 'IGNORA_AGENTES_OPERACOES' in os.environ:
         self.agentes_ignorar = set(os.environ['IGNORA_AGENTES_OPERACOES'].split("-"))
 def test_basic(self):
     driver = None
     driver = ChromeDriver()
     driver.get('https://www.oursky.com/')
     el = driver.find_element_by_class_name('btn-header')
     assert str(el.text).upper() == 'START YOUR PROJECT'
 def test_basic(self):
     driver = ChromeDriver()
     driver.get('https://palafiita.com/ofertas-publicas/')
     el = driver.find_element_by_class_name('site-description')
     assert str(el.text) == 'Investimentos em Fundos Imobiliários'
Exemple #7
0
 def __init__(self):
     from src.driver_selenium import ChromeDriver
     self.driver = ChromeDriver()
Exemple #8
0
class CrawlerAdvfn():

    def __init__(self):
        from src.driver_selenium import ChromeDriver
        self.driver = ChromeDriver()

    def __get_url(self, ticker):
        return 'https://br.advfn.com/bolsa-de-valores/bmf/{ticker}/cotacao'.format(ticker=ticker)

    def busca_preco_atual(self, ticker):
        ticker = ticker.lower()

        if ticker in this.cache:
            return this.cache[ticker]['preco_atual']
        else:
            try:
                this.cache[ticker] = self.__recupera_informacoes(ticker)

                return this.cache[ticker]['preco_atual']

            except Exception as ex:
                logger.exception('busca_preco_atual ticker: {ticker}'.format(ticker=ticker))
                return None

    def busca_tipo_ticker(self, ticker):
        ticker = ticker.lower()

        if ticker in this.cache:
            return this.cache[ticker]['tipo_ticker']
        else:
            try:
                this.cache[ticker] = self.__recupera_informacoes(ticker)

                return this.cache[ticker]['tipo_ticker']

            except Exception as ex:
                logger.exception('busca_tipo_ticker ticker: {ticker}'.format(ticker=ticker))
                return None

    def __recupera_informacoes(self, ticker):
        self.driver.get(self.__get_url(ticker))

        preco_atual = self.__recupera_preco_atual()

        tipo_ticker = self.__recupera_tipo_ticker()

        return {'tipo_ticker': tipo_ticker, 'preco_atual': preco_atual}

    def __recupera_preco_atual(self):
        try:
            WebDriverWait(self.driver, 10).until(EC.visibility_of_element_located((By.ID, 'quoteElementPiece10')))
            preco_atual = float(self.driver.find_element_by_id('quoteElementPiece10').text
                                .replace('.', '').replace(',', '.'))
            return preco_atual
        except Exception as ex:
            return None

    def __recupera_tipo_ticker(self):
        WebDriverWait(self.driver, 10).until(EC.visibility_of_element_located((By.ID, 'quoteElementPiece5')))
        tipo = self.driver.find_element_by_id('quoteElementPiece5').text.lower()

        if tipo == 'futuro':
            return TipoTicker.FUTURO

        if tipo == 'opção':
            return TipoTicker.OPCAO

        if tipo == 'preferencial' or tipo == 'ordinária':
            return TipoTicker.ACAO

        if tipo == 'fundo':
            if self.__fundo_eh_fii():
                return TipoTicker.FII

            if self.__fundo_eh_etf():
                return TipoTicker.ETF

        return None

    def __fundo_eh_etf(self):
        if 'Exchange Traded Fund' in self.driver.page_source:
            return True
        return False

    def __fundo_eh_fii(self):
        try:
            nome = self.driver.find_elements_by_class_name("page-name-h1")[0].text.lower()
            dividendos = self.__converte_tabela_dividendos_para_df();

            if 'FII' in nome.upper() and len(dividendos):
                return True
            else:
                return False
        except:
            return False

    def __converte_tabela_dividendos_para_df(self):
        try:
            soup = BeautifulSoup(self.driver.page_source, 'html.parser')

            table = soup.find('table', {'id': 'id_stocks_dividends'})

            df = pd.read_html(str(table), decimal=',', thousands='.')[0]

            return df
        except:
            return None
Exemple #9
0
class CrawlerCei():
    def __init__(self, headless=False, directory=None, debug=False):
        self.BASE_URL = 'https://ceiapp.b3.com.br/CEI_Responsivo/'
        self.driver = ChromeDriver()
        self.directory = directory
        self.debug = debug
        self.__colunas_df_cei = [
            'Data do Negócio', 'Compra/Venda', 'Mercado', 'Prazo/Vencimento',
            'Código Negociação', 'Especificação do Ativo', 'Quantidade',
            'Preço (R$)', 'Valor Total(R$)', 'Fator de Cotação'
        ]
        self.id_tabela_negociacao_ativos = 'ctl00_ContentPlaceHolder1_rptAgenteBolsa_ctl00_rptContaBolsa_ctl00_pnAtivosNegociados'
        self.id_mensagem_de_aviso = 'CEIMessageDIV'
        self.id_selecao_corretoras = 'ctl00_ContentPlaceHolder1_ddlAgentes'
        self.id_btn_consultar = 'ctl00_ContentPlaceHolder1_btnConsultar'

    def busca_trades(self):
        try:
            self.driver.get(self.BASE_URL)
            self.__login()
            df = self.__abre_consulta_trades()
            return self.__converte_dataframe_para_formato_padrao(df)
        except Exception as ex:
            raise ex
        finally:
            self.driver.quit()

    def __login(self):
        if self.debug: self.driver.save_screenshot(self.directory + r'01.png')
        txt_login = self.driver.find_element_by_id(
            'ctl00_ContentPlaceHolder1_txtLogin')
        txt_login.clear()
        txt_login.send_keys(os.environ['CPF'])

        time.sleep(3.0)
        txt_senha = self.driver.find_element_by_id(
            'ctl00_ContentPlaceHolder1_txtSenha')
        txt_senha.clear()
        txt_senha.send_keys(os.environ['SENHA_CEI'])
        time.sleep(3.0)

        if self.debug: self.driver.save_screenshot(self.directory + r'02.png')

        btn_logar = self.driver.find_element_by_id(
            'ctl00_ContentPlaceHolder1_btnLogar')
        btn_logar.click()

        try:
            WebDriverWait(self.driver, 60).until(
                EC.visibility_of_element_located((By.ID, 'objGrafPosiInv')))
        except Exception as ex:
            raise Exception(
                'Nao foi possivel logar no CEI. Possivelmente usuario/senha errada ou indisponibilidade do site'
            )

        if self.debug: self.driver.save_screenshot(self.directory + r'03.png')

    def __abre_consulta_trades(self):
        def consultar_click(driver):
            btn_consultar = WebDriverWait(driver, 20).until(
                EC.element_to_be_clickable((By.ID, self.id_btn_consultar)))
            btn_consultar.click()

        def exists_and_not_disabled(id):
            def until_fn(driver):
                try:
                    driver.find_element_by_id(id)
                except NoSuchElementException:
                    return False
                return driver.find_element_by_id(id).get_attribute(
                    "disabled") is None

            return until_fn

        dfs_to_concat = []

        self.driver.get(self.BASE_URL + 'negociacao-de-ativos.aspx')
        if self.debug: self.driver.save_screenshot(self.directory + r'04.png')

        from selenium.webdriver.support.select import Select
        ddlAgentes = Select(
            self.driver.find_element_by_id(self.id_selecao_corretoras))

        def __busca_trades_de_uma_corretora(i):
            if self.debug:
                self.driver.save_screenshot(self.directory + r'04_01.png')
            ddlAgentes = Select(
                self.driver.find_element_by_id(self.id_selecao_corretoras))
            ddlAgentes.select_by_index(i)
            time.sleep(10)
            if self.debug:
                self.driver.save_screenshot(self.directory + r'04_02.png')
            WebDriverWait(self.driver, 15).until(
                exists_and_not_disabled(self.id_btn_consultar))
            consultar_click(self.driver)

            if self.debug:
                self.driver.save_screenshot(self.directory + r'05.png')

            try:
                WebDriverWait(self.driver, 10).until(
                    EC.visibility_of_element_located(
                        (By.ID, self.id_mensagem_de_aviso)))
            except:
                pass

            if self.debug:
                self.driver.save_screenshot(self.directory + r'06.png')

            # checa se existem trades para essa corretora
            aviso = self.driver.find_element_by_id(self.id_mensagem_de_aviso)
            if aviso.text == 'Não foram encontrados resultados para esta pesquisa.\n×':
                consultar_click(self.driver)
                WebDriverWait(self.driver, 60).until(
                    exists_and_not_disabled(self.id_selecao_corretoras))
            else:
                if not exists_and_not_disabled(
                        self.id_tabela_negociacao_ativos)(self.driver):
                    consultar_click(self.driver)

                WebDriverWait(self.driver, 30).until(
                    EC.visibility_of_element_located(
                        (By.ID, self.id_tabela_negociacao_ativos)))

                dfs_to_concat.append(self.__converte_trades_para_dataframe())
                consultar_click(self.driver)
                WebDriverWait(self.driver, 60).until(
                    exists_and_not_disabled(self.id_selecao_corretoras))

        if len(ddlAgentes.options) == 1:
            __busca_trades_de_uma_corretora(0)
        else:
            for i in range(1, len(ddlAgentes.options)):
                __busca_trades_de_uma_corretora(i)

        if len(dfs_to_concat):
            return pd.concat(dfs_to_concat)
        else:
            return pd.DataFrame(columns=self.__colunas_df_cei)

    def __converte_trades_para_dataframe(self):

        soup = BeautifulSoup(self.driver.page_source, 'html.parser')

        top_div = soup.find('div', {'id': self.id_tabela_negociacao_ativos})

        table = top_div.find(lambda tag: tag.name == 'table')

        df = pd.read_html(str(table), decimal=',', thousands='.')[0]

        df = df.dropna(subset=['Mercado'])
        return df

    def __converte_dataframe_para_formato_padrao(self, df):
        df = df.rename(
            columns={
                'Código Negociação': 'ticker',
                'Compra/Venda': 'operacao',
                'Quantidade': 'qtd',
                'Data do Negócio': 'data',
                'Preço (R$)': 'preco',
                'Valor Total(R$)': 'valor'
            })

        from src.stuff import calculate_add

        def formata_compra_venda(operacao):
            if operacao == 'V':
                return 'Venda'
            else:
                return 'Compra'

        def remove_fracionado_ticker(ticker):
            return ticker[:-1] if ticker.endswith('F') else ticker

        df['data'] = pd.to_datetime(df['data'], dayfirst=True)
        df['data'] = df['data'].dt.date
        df['ticker'] = df.apply(
            lambda row: remove_fracionado_ticker(row.ticker), axis=1)
        df['operacao'] = df.apply(
            lambda row: formata_compra_venda(row.operacao), axis=1)
        df['qtd_ajustada'] = df.apply(lambda row: calculate_add(row), axis=1)

        df['taxas'] = 0.0
        df['aquisicao_via'] = 'HomeBroker'

        df.drop(columns=[
            'Mercado', 'Prazo/Vencimento', 'Especificação do Ativo',
            'Fator de Cotação'
        ],
                inplace=True)
        return df
Exemple #10
0
class CrawlerCei():

    def __init__(self, headless=False, directory='./temp/', debug=False):
        self.BASE_URL = 'https://ceiapp.b3.com.br/CEI_Responsivo/'
        self.driver = ChromeDriver()
        self.directory = directory
        self.debug = debug
        self.__colunas_df_cei = ['Data do Negócio', 'Compra/Venda', 'Mercado', 'Prazo/Vencimento', 'Código Negociação',
               'Especificação do Ativo', 'Quantidade', 'Preço (R$)', 'Valor Total(R$)', 'Fator de Cotação']
        self.__colunas_df_carteira = ['Empresa', 'Tipo', 'ticker', 'isin', 'Preço (R$)',
               'Quantidade', 'Fator de Cotação' 'Valor Total(R$)']
        self.id_tabela_negociacao_ativos = 'ctl00_ContentPlaceHolder1_rptAgenteBolsa_ctl00_rptContaBolsa_ctl00_pnAtivosNegociados'
        self.id_mensagem_de_aviso = 'CEIMessageDIV'
        self.id_selecao_corretoras = 'ctl00_ContentPlaceHolder1_ddlAgentes'
        self.id_btn_consultar = 'ctl00_ContentPlaceHolder1_btnConsultar'
        self.id_selecao_data = 'ctl00_ContentPlaceHolder1_txtData'
        self.agentes_ignorar = {}
        if 'IGNORA_AGENTES_OPERACOES' in os.environ:
            self.agentes_ignorar = set(os.environ['IGNORA_AGENTES_OPERACOES'].split("-"))
        

    def busca_trades(self, dropExtras=True):
        try:
            print("Buscando operações CEI para " + os.environ['CPF'])
            if (os.getenv("SENHA_CEI","") == ""):
                raise Exception("Senha CEI não está definida")
            self.driver.get(self.BASE_URL)
            self.__login()
            df = self.__abre_consulta_trades()
            try:
                return self.__converte_dataframe_para_formato_padrao(df, dropExtras)
            except Exception as ex:
                if self.debug:
                    print("*** Erro buscando operações")
                    print(df)
                raise ex
        except Exception as ex:
            self.__save_screenshot('erro_busca_trades-' + datetime.datetime.now().strftime('%Y-%m-%d-%H-%M') + '.png', force_save=True)
            raise ex
        finally:
            self.driver.quit()

    def busca_carteira(self, data):
        try:
            print("Buscando carteira CEI para " + os.environ['CPF'] + " " + str(data))
            if (os.getenv("SENHA_CEI","") == ""):
                raise Exception("Senha CEI não está definida")
            self.driver.get(self.BASE_URL)
            self.__login()
            df = self.__abre_consulta_carteira(data)
            return df
        except Exception as ex:
            self.__save_screenshot('erro_busca_carteira-' + datetime.datetime.now().strftime('%Y-%m-%d-%H-%M') + '.png', force_save=True)
            raise ex
        finally:
            self.driver.quit()

    def converte_html_carteira(self, html):
        try:
            df = self.__converte_custodia_html_para_dataframe(html, 0, 'Todos')
            return df
        except Exception as ex:
            raise ex

    def __save_screenshot(self, name, force_save=False):
        if self.debug or force_save:
            self.driver.save_screenshot(self.directory + name)
    
    def __login(self):
        self.__save_screenshot(r'01-inicio.png')
        
        txt_login = self.driver.find_element_by_id('ctl00_ContentPlaceHolder1_txtLogin')
        txt_login.clear()
        txt_login.send_keys(os.environ['CPF'])

        time.sleep(3.0)
        txt_senha = self.driver.find_element_by_id('ctl00_ContentPlaceHolder1_txtSenha')
        txt_senha.clear()
        txt_senha.send_keys(os.environ['SENHA_CEI'])
        time.sleep(3.0)

        self.__save_screenshot(r'02-dados-login.png')

        btn_logar = self.driver.find_element_by_id('ctl00_ContentPlaceHolder1_btnLogar')
        btn_logar.click()

        try:
            WebDriverWait(self.driver, 60).until(EC.visibility_of_element_located((By.ID, 'objGrafPosiInv')))
        except Exception as ex:
            self.__save_screenshot(r'03-erro-login.png')
            raise Exception('Nao foi possivel logar no CEI. Possivelmente usuario/senha errada ou indisponibilidade do site') from ex

        self.__save_screenshot(r'03-pos-login.png')

    def consultar_click(self, driver):
        btn_consultar = WebDriverWait(driver, 20).until(
            EC.element_to_be_clickable((By.ID, self.id_btn_consultar)))
        btn_consultar.click();

    def exists_and_not_disabled(self, id):
        def until_fn(driver):
            try:
                driver.find_element_by_id(id)
            except NoSuchElementException:
                return False
            return driver.find_element_by_id(id).get_attribute("disabled") is None

        return until_fn

    def __abre_consulta_trades(self):

        dfs_to_concat = []

        self.driver.get(self.BASE_URL + 'negociacao-de-ativos.aspx')
        self.__save_screenshot(r'04-negociacao-ativos.png')

        from selenium.webdriver.support.select import Select
        ddlAgentes = Select(self.driver.find_element_by_id(self.id_selecao_corretoras))

        def __busca_trades_de_uma_corretora(i, nomeAgente):
            print("Verificando Operações : " + str(i) + " " + nomeAgente)
            # O nome do agente é um número/ código e depois vem o nome
            # Utilizar isso para ignorar alguns agentes, não existe motivo para tentar buscar operações se o usuário não faz operações com o agente...
            #  3 - XP INVESTIMENTOS CCTVM S/A
            numeroAgente = nomeAgente.split(" ")[0]
            if numeroAgente in self.agentes_ignorar:
                print("\tIgnorando agente no download de operações")
                return
                
            self.__save_screenshot(r'05_01-' + str(i) + '.png')
            ddlAgentes = Select(self.driver.find_element_by_id(self.id_selecao_corretoras))
            ddlAgentes.select_by_index(i)
            time.sleep(10)
            
            self.__save_screenshot(r'05_02-' + str(i) + '.png')
            WebDriverWait(self.driver, 15).until(self.exists_and_not_disabled(self.id_btn_consultar))
            self.consultar_click(self.driver)

            self.__save_screenshot(r'05_03-' + str(i) + '.png')

            try:
                WebDriverWait(self.driver, 10).until(EC.visibility_of_element_located(
                    (By.ID, self.id_mensagem_de_aviso)))
            except:
                pass

            self.__save_screenshot(r'05_04-' + str(i) + '.png')

            # checa se existem trades para essa corretora
            aviso = self.driver.find_element_by_id(self.id_mensagem_de_aviso)
            if aviso.text == 'Não foram encontrados resultados para esta pesquisa.\n×':
                self.consultar_click(self.driver)
                try:
                    WebDriverWait(self.driver, 60).until(self.exists_and_not_disabled(self.id_selecao_corretoras))
                    self.__save_screenshot(r'05_05-sem-resultados-' + str(i) + '.png')
                except StaleElementReferenceException as ex:
                    # Pode ignorar já que não teve dados
                    pass
                print("\tNão existem operações")
            else:
                if not self.exists_and_not_disabled(self.id_tabela_negociacao_ativos)(self.driver):
                    self.consultar_click(self.driver)

                WebDriverWait(self.driver, 30).until(EC.visibility_of_element_located(
                    (By.ID, self.id_tabela_negociacao_ativos)))

                self.__save_screenshot(r'05_05-' + str(i) + '.png')
                operacoes = self.__converte_trades_para_dataframe(i, nomeAgente)
                print("\tOperações encontradas : " + str(len(operacoes)))
                dfs_to_concat.append(operacoes)
                self.consultar_click(self.driver)
                WebDriverWait(self.driver, 60).until(self.exists_and_not_disabled(self.id_selecao_corretoras))

        # Durante as buscas os elementos se alteram e o selenium nao consegue obter o texto correto, então salva antes
        opcoesAgentes = ddlAgentes.options
        textosAgentes = []
        for i in range(0,len(opcoesAgentes)):
            textosAgentes.append(opcoesAgentes[i].text)
        # Quando tem mais de um a primeira linha é um texto "Selecione"
        if len(opcoesAgentes) == 1:
            __busca_trades_de_uma_corretora(0, textosAgentes[0])
        else:
            for i in range(1, len(opcoesAgentes)):
                __busca_trades_de_uma_corretora(i, textosAgentes[i])

        if len(dfs_to_concat):
            return pd.concat(dfs_to_concat)
        else:
            return pd.DataFrame(columns=self.__colunas_df_cei)

    def __converte_trades_para_dataframe(self, i, nomeAgente):

        soup = BeautifulSoup(self.driver.page_source, 'html.parser')
        if self.debug:
            with open(self.directory + "trades-" + str(i) + ".html", "w") as file:
                file.write(soup.prettify())

        top_div = soup.find('div', {'id': self.id_tabela_negociacao_ativos})

        table = top_div.find(lambda tag: tag.name == 'table')
        if self.debug:
            with open(self.directory + "trades-" + str(i) + "-tabela.html", "w") as file:
                file.write(table.prettify())

        df = pd.read_html(str(table), decimal=',', thousands='.')[0]
        df['agente'] = df.apply(lambda row: nomeAgente, axis=1)
        
        if self.debug:
            with open(self.directory + "trades-" + str(i) + ".txt", "w") as file:
                file.write(tabulate(df, headers=df.columns, showindex=True, tablefmt='psql'))
        # Remove totais que vem tambem na tabela
        df = df[df['Data do Negócio'].str.match('\\d+/\\d+/\\d+')]
        if self.debug:
            with open(self.directory + "trades-" + str(i) + "-filtro.txt", "w") as file:
                file.write(tabulate(df, headers=df.columns, showindex=True, tablefmt='psql'))
        
        return df


    def __converte_dataframe_para_formato_padrao(self, df, dropExtras):
        df = df.rename(columns={'Código Negociação': 'ticker',
                                'Compra/Venda': 'operacao',
                                'Quantidade': 'qtd',
                                'Data do Negócio': 'data',
                                'Preço (R$)': 'preco',
                                'Valor Total(R$)': 'valor',
                                })

        from src.stuff import calculate_add

        def formata_compra_venda(operacao):
            if operacao == 'V':
                return 'Venda'
            else:
                return 'Compra'

        def remove_fracionado_ticker(ticker):
            return ticker[:-1] if ticker.endswith('F') else ticker

        df['data'] = pd.to_datetime(df['data'], dayfirst=True)
        df['data'] = df['data'].dt.date
        df['ticker'] = df.apply(lambda row: remove_fracionado_ticker(row.ticker), axis=1)
        df['operacao'] = df.apply(lambda row: formata_compra_venda(row.operacao), axis=1)
        df['qtd_ajustada'] = df.apply(lambda row: calculate_add(row), axis=1)

        df['taxas'] = 0.0
        df['aquisicao_via'] = 'HomeBroker'

        if dropExtras:
            df.drop(columns=['Mercado', 
                         'Prazo/Vencimento', 
                         'Especificação do Ativo',
                         'Fator de Cotação'], 
                         inplace=True)
        return df

    def __abre_consulta_carteira(self, data):

        dfs_to_concat = []

        self.driver.get(self.BASE_URL + 'ConsultarCarteiraAtivos.aspx')
        self.__save_screenshot(r'04-carteira-ativos.png')

        from selenium.webdriver.support.select import Select
        ddlAgentes = Select(self.driver.find_element_by_id(self.id_selecao_corretoras))

        def __busca_ativos_de_uma_corretora(i, nomeAgente):
            print("Verificando Carteira : " + str(i) + " " + nomeAgente)
            
            self.__save_screenshot(r'05_01-' + str(i) + '.png')
            ddlAgentes = Select(self.driver.find_element_by_id(self.id_selecao_corretoras))
            ddlAgentes.select_by_index(i)
            time.sleep(10)
            
            self.__save_screenshot(r'05_02-' + str(i) + '.png')            
            inputData = self.driver.find_element_by_id(self.id_selecao_data)
            inputData.clear()
            inputData.send_keys(data.strftime('%d/%m/%Y'))
            time.sleep(10)
            
            self.__save_screenshot(r'05_03-' + str(i) + '.png')            
            WebDriverWait(self.driver, 15).until(self.exists_and_not_disabled(self.id_btn_consultar))
            self.consultar_click(self.driver)

            self.__save_screenshot(r'05_04-' + str(i) + '.png')

            try:
                WebDriverWait(self.driver, 10).until(EC.visibility_of_element_located(
                    (By.ID, self.id_mensagem_de_aviso)))
            except:
                pass

            self.__save_screenshot(r'05_05-' + str(i) + '.png')

            # checa se existem trades para essa corretora
            aviso = self.driver.find_element_by_id(self.id_mensagem_de_aviso)
            if aviso.text == 'Não foram encontrados resultados para esta pesquisa.\n×':
                self.consultar_click(self.driver)
                try:
                    WebDriverWait(self.driver, 60).until(self.exists_and_not_disabled(self.id_selecao_corretoras))
                    self.__save_screenshot(r'05_06-sem-resultados-' + str(i) + '.png')
                except StaleElementReferenceException as ex:
                    # Pode ignorar já que não teve dados
                    pass
            else:
                self.__save_screenshot(r'05_06-' + str(i) + '.png')
                dfs_to_concat.append(self.__converte_custodia_para_dataframe(i, nomeAgente))
                self.consultar_click(self.driver)
                WebDriverWait(self.driver, 60).until(self.exists_and_not_disabled(self.id_selecao_corretoras))

        # Durante as buscas os elementos se alteram e o selenium nao consegue obter o texto correto, então salva antes
        opcoesAgentes = ddlAgentes.options
        textosAgentes = []
        for i in range(0,len(opcoesAgentes)):
            textosAgentes.append(opcoesAgentes[i].text)
        # A primeira opção é Todos e depois tem as corretoras, parece funcionar bem com todas de uma vez
        __busca_ativos_de_uma_corretora(0, textosAgentes[0])
#        if len(opcoesAgentes) == 1:
#            __busca_ativos_de_uma_corretora(0, textosAgentes[0])
#        else:
#            for i in range(1, len(opcoesAgentes)):
#                __busca_ativos_de_uma_corretora(i, textosAgentes[i])

        if len(dfs_to_concat):
            return pd.concat(dfs_to_concat)
        else:
            return pd.DataFrame(columns=self.__colunas_df_carteira)

    def __converte_custodia_para_dataframe(self, i, nomeAgente):
        return self.__converte_custodia_html_para_dataframe(self.driver.page_source, i, nomeAgente)

    # Separação desse metodo facilita nos testes utilizando html local
    def __converte_custodia_html_para_dataframe(self, html_source, i, nomeAgente):

        dfs_to_concat = []
        
        soup = BeautifulSoup(html_source, 'html.parser')
        if self.debug:
            with open(self.directory + "custodia-" + str(i) + ".html", "w") as file:
                file.write(soup.prettify())


        nomeEl = soup.findAll('span',id=re.compile('ctl00_ContentPlaceHolder1_rptAgenteContaMercado_ctl\\d\\d_lblAgenteContas'))
        for el in nomeEl:
            agente = el.text.strip()
            conta = ''
            # ctl00_ContentPlaceHolder1_rptAgenteContaMercado_ctl00_rptContaMercado_ctl00_lblContaPosicao
            nextId = el['id'].replace('lblAgenteContas','rptContaMercado_ctl\\d\\d_lblContaPosicao')
            next = el.find_parent('div').find_next_sibling('div').find(id=re.compile(nextId))
            if next:
                conta = next.text.strip()

            # ctl00_ContentPlaceHolder1_rptAgenteContaMercado_ctl00_rptContaMercado_ctl00_rprCarteira_ctl00_trBodyCarteira
            nextId = el['id'].replace('lblAgenteContas','rptContaMercado_ctl\\d\\d_rprCarteira_ctl\\d\\d_trBodyCarteira')
            nextTables = el.find_parent('div').find_next_sibling('div').findAll(id=re.compile(nextId))
            for next in nextTables:
                # id="ctl00_ContentPlaceHolder1_rptAgenteContaMercado_ctl02_rptContaMercado_ctl00_rprCarteira_ctl00_lblCarteira"
                nextId = next['id'].replace('trBodyCarteira','lblCarteira')
                lbl = next.find(id=re.compile(nextId))
                carteira = ''
                if lbl:
                    carteira = lbl.text.strip()
                table = next.find('table')
                df = pd.read_html(str(table), decimal=',', thousands='.')[0]
                df['agente'] = df.apply(lambda row: agente, axis=1)
                df['conta'] = df.apply(lambda row: conta, axis=1)
                df['carteira'] = df.apply(lambda row: carteira, axis=1)
                if self.debug:
                    with open(self.directory + "custodia-" + str(i) + "-" + str(len(dfs_to_concat)) + ".html", "w") as file:
                        file.write(table.prettify())

                    with open(self.directory + "custodia-" + str(i) + "-" + str(len(dfs_to_concat)) + "-filtro.txt", "w") as file:
                        file.write(tabulate(df, headers=df.columns, showindex=True, tablefmt='psql'))
                dfs_to_concat.append(df)
        df = pd.concat(dfs_to_concat, ignore_index=True)
        # As linhas de total vem com Nan            
        df = df.dropna()
        df = df.rename(columns={'Empresa': 'empresa',
                                'Tipo': 'tipo',
                                'Cód. de Negociação': 'ticker',
                                'Cod.ISIN': 'isin',
                                'Preço (R$)*': 'preco',
                                'Qtde.': 'qtd',
                                'Fator Cotação': 'fator',
                                'Valor (R$)': 'valor',
                                })
        if self.debug:
            with open(self.directory + "custodia-" + str(i) + "-" + str(len(dfs_to_concat)) + "-combinado.txt", "w") as file:
                file.write(tabulate(df, headers=df.columns, showindex=True, tablefmt='psql'))
        
        return df


        
Exemple #11
0
class CrawlerAdvfn():
    def __init__(self):
        from src.driver_selenium import ChromeDriver
        self.driver = ChromeDriver()

    def __get_url(self, ticker):
        return 'https://br.advfn.com/bolsa-de-valores/bmf/{ticker}/cotacao'.format(
            ticker=ticker)

    def __get_url_fundamentos(self, ticker):
        return 'https://br.advfn.com/bolsa-de-valores/bovespa/{ticker}/fundamentos'.format(
            ticker=ticker)

    def recupera_informacoes(self, ticker):
        self.driver.get(self.__get_url(ticker))

        tipo_ticker = self.__recupera_tipo_ticker(ticker)

        preco_atual = self.__recupera_preco_atual()

        if tipo_ticker == TipoTicker.ACAO:
            self.driver.get(self.__get_url_fundamentos(ticker))
            p_vp = self.__recupera_p_vp()
        else:
            p_vp = None

        return {
            'tipo_ticker': tipo_ticker,
            'preco_atual': preco_atual,
            'p_vp': p_vp
        }

    def __recupera_preco_atual(self):
        try:
            WebDriverWait(self.driver, 10).until(
                EC.visibility_of_element_located(
                    (By.ID, 'quoteElementPiece10')))
            preco_atual = float(
                self.driver.find_element_by_id(
                    'quoteElementPiece10').text.replace('.',
                                                        '').replace(',', '.'))
            return preco_atual
        except Exception as ex:
            return None

    def __recupera_tipo_ticker(self, ticker):
        try:
            WebDriverWait(self.driver, 10).until(
                EC.visibility_of_element_located(
                    (By.ID, 'quoteElementPiece5')))
            tipo = self.driver.find_element_by_id(
                'quoteElementPiece5').text.lower()
            isin = self.driver.find_element_by_id(
                'quoteElementPiece6').text.lower()

            if tipo == 'futuro':
                return TipoTicker.FUTURO

            if tipo == 'opção':
                return TipoTicker.OPCAO

            if tipo == 'preferencial' or tipo == 'ordinária':
                return TipoTicker.ACAO

            if tipo == 'fundo':
                if self.__fundo_eh_fii():
                    return TipoTicker.FII

                if self.__fundo_eh_etf():
                    return TipoTicker.ETF

            if (tipo == 'recibo de depósito') and ('bdr' in isin):
                return TipoTicker.BDR
        except Exception as ex:
            print("** Erro buscando tipo do ticker " + ticker)
            print(ex)
        return None

    def __recupera_p_vp(self):
        WebDriverWait(self.driver, 15).until(
            EC.visibility_of_element_located((By.ID, 'content')))
        soup = BeautifulSoup(self.driver.page_source, 'html.parser')

        # Tem diversas tabelas com mesma classe
        tables = soup.find_all('table', {'class': 'fundamentals-table'})
        if tables is None:
            return None
        for table in tables:
            rows = table.find_all("tr")

            for row in rows:
                cells = row.find_all("td")
                if 'P/VPA' in cells[0].get_text():
                    p_vpa = cells[1].get_text().replace('.',
                                                        '').replace(',', '.')
                    if (p_vpa != 'N/D') and (p_vpa != '0.00'):
                        return float(p_vpa)
        return None

    def __fundo_eh_etf(self):
        if 'Exchange Traded Fund' in self.driver.page_source:
            return True
        return False

    def __fundo_eh_fii(self):
        try:
            nome = self.driver.find_elements_by_class_name(
                "page-name-h1")[0].text.lower()
            dividendos = self.__converte_tabela_dividendos_para_df()

            if 'FII' in nome.upper() and len(dividendos):
                return True
            else:
                return False
        except:
            return False

    def __converte_tabela_dividendos_para_df(self):
        try:
            soup = BeautifulSoup(self.driver.page_source, 'html.parser')

            table = soup.find('table', {'id': 'id_stocks_dividends'})

            df = pd.read_html(str(table), decimal=',', thousands='.')[0]

            return df
        except:
            return None
Exemple #12
0
def __busca_etfs_na_b3_cache():
    url = 'http://bvmf.bmfbovespa.com.br/etf/fundo-de-indice.aspx?idioma=pt-br&aba=tabETFsRendaVariavel'
    driver = ChromeDriver()
    driver.get(url)

    return __converte_etfs_para_dataframe(driver)