Solucionado (ver solução)
Solucionado
(ver solução)
12
respostas

Scraping em site que não permite.

Estou tentando fazer um programa onde ele busca informações de um site e depois faz o scraping dos dados, o problema é que o site sempre manda um erro, até agora eu não consegui nem passar das três barras de busca do site, a única forma que consegui de para extrair algo foi com o selenium. site: https://www.oi.com.br/minha-oi/102busca/

12 respostas

Olá Luis,

Como está o seu código atual? Qual é o erro que aparece?

Pelo que eu vi o site depende de javascript para gerar boa parte do conteúdo, por causa disso realmente é necessário o uso do selenium como você mencionou.

from selenium import webdriver
from time import sleep
from selenium.webdriver.common.keys import Keys
from webdriver_manager.chrome import ChromeDriverManager
from selenium.webdriver.common.by import By

import os, sys
import time, requests
from bs4 import BeautifulSoup


delayTime = 2
audioToTextDelay = 10
filename = 'test.mp3'
byPassUrl = 'https://www.oi.com.br/minha-oi/102busca/'
googleIBMLink = 'https://speech-to-text-demo.ng.bluemix.net/'

option = webdriver.ChromeOptions()
option.add_argument('--disable-notifications')
'option.add_argument("--mute-audio")'

option.add_argument(
    "user-agent=Mozilla/5.0 (iPhone; CPU iPhone OS 10_3 like Mac OS X) AppleWebKit/602.1.50 (KHTML, like Gecko) CriOS/56.0.2924.75 Mobile/14E5239e Safari/602.1")


def audioToText(mp3Path):
    driver.execute_script('''window.open("","_blank");''')
    driver.switch_to.window(driver.window_handles[1])

    driver.get(googleIBMLink)
    sleep(6)


    time.sleep(1)
    root = driver.find_element_by_id('root').find_elements_by_class_name('dropzone _container _container_large')
    btn = driver.find_element(By.XPATH, '//*[@id="root"]/div/input')
    btn.send_keys(mp3Path)

    time.sleep(audioToTextDelay)

    text = driver.find_element(By.XPATH, '//*[@id="root"]/div/div[6]/div/div/dialog').find_elements_by_tag_name('dd')
    result = " ".join([each.text for each in text])

    driver.close()
    driver.switch_to.window(driver.window_handles[0])

    return result

def saveFile(content, filename):
    with open(filename, "wb") as handle:
        for data in content.iter_content():
            handle.write(data)


driver = webdriver.Chrome(ChromeDriverManager().install(), chrome_options=option)
driver.get(byPassUrl)
sleep(7)


driver.find_element_by_id('input-nome-razao-social').send_keys('oao')
driver.find_element_by_css_selector('[placeholder="UF"]').send_keys('rs')
sleep(1)
driver.find_element_by_xpath('//*[@id="application"]/div/div[3]/div/div/div/div[1]/div[2]/div[1]/div/div/div[2]/button').click()


sleep(2)
driver.find_element_by_css_selector('[placeholder="Cidade"]').send_keys('porto alegre')
sleep(2)
driver.find_element_by_xpath('//*[@id="application"]/div/div[3]/div/div/div/div[1]/div[2]/div[2]/div/div/div[2]/button').click()
sleep(1)
driver.find_element_by_css_selector('[class $="btn"]').click()
sleep(2)


allIframesLen = driver.find_elements_by_tag_name('iframe')
audioBtnFound = False
audioBtnIndex = -1
 break
    except Exception as e:
        pass

if audioBtnFound:
    try:
        while True:
            href = driver.find_element_by_id('audio-source').get_attribute('src')
            response = requests.get(href, stream=True)
            saveFile(response, filename)
            response = audioToText(os.getcwd() + '/' + filename)
            print(response)

            driver.switch_to_default_content()
            iframe = driver.find_elements_by_tag_name('iframe')[audioBtnIndex]
            driver.switch_to.frame(iframe)

            inputbtn = driver.find_element_by_id('audio-response')
            inputbtn.send_keys(response)
            inputbtn.send_keys(Keys.ENTER)

            time.sleep(2)
            errorMsg = driver.find_elements_by_class_name('rc-audiochallenge-error-message')[0]

            if errorMsg.text == "" or errorMsg.value_of_css_property('display') == 'none':
                print("Successo")
                break


  except Exception as e:
        print(e)
        print('Cuidado. É preciso trocar o proxy')
else:
    print('Botão não encontrado')










Eu mandei o código se você quiser dar uma olhada, meus problemas atuais são os seguintes. 1) o captcha fica detectando toda hora o selenium, por isso tenho que ficar o tempo todo trocando de proxy e isso também reduz drasticamente minhas tentativas de achar alternativas porque testo pouco.

2) o método que estou testando agora é através da IA de reconhecimento de voz da IBM, o site está no código, o problema que ele também fica me spamando na tela pop, por causa do selenium. 3) Não sei se vou ter problemas se caso eu passar do captcha, por isso quero sua opnião.

O captcha realmente é um obstáculo muito grande, só em já ter passado por isso algumas vezes já conseguiu ir bem longe.

O objetivo então seria fazer o que? Buscar as pessoas pelo site da OI e utilizar essas informações no site da IBM ou são dois projetos separados?

Eu fiz muitos testes com o scraping da OI mas sem muito sucesso. Conseguindo passar pelo captcha um código simples como o abaixo já é o suficiente para pegar todos os resultados:

soup = BeautifulSoup(driver.page_source)
results = soup.findAll('div', {'class': 'content-result'})

pessoas = []

for item in results:
    p = {}
    p['name'] = item.find('h1').getText()
    p['phone'] = item.find('p').getText().replace(' Telefone: ', '')
    p['address'] = item.findAll('p')[1].getText().replace(' Endereço:  ', '')

    pessoas.append(p)

pessoas

Infelizmente eu não posso ajudar com o obstáculo do captcha que é o problema principal.

O site da IBM era pra fazer o reconhecimento do voz do captcha, eu passei três vezes, só que em muita tentativas. Você poderia colocar o código completo? Eu precisava pesquisar a pessoa pelo nome, estado e cidade, você acha que é possivel?

O meu deu erro, por favor coloque o código inteiro.

solução!

Não sei se o meu código pode ajudar muito pois não resolve a questão do captcha, o que eu fiz foi resolver o captcha manualmente na metade da exeecução do script para então buscar os dados das pessoas.

Eu utilizei o código abaixo para iniciar o scraping:

from selenium import webdriver
from bs4 import BeautifulSoup
from time import sleep

url = 'https://www.oi.com.br/minha-oi/102busca/'

driver = webdriver.Chrome(executable_path='C:\selenium\chromedriver.exe')
driver.get(url)

sleep(5)
driver.find_element_by_id('input-nome-razao-social').send_keys('oao')
sleep(1)
driver.find_element_by_css_selector('[placeholder="UF"]').send_keys('rs')
sleep(1)
driver.find_element_by_xpath('//button[@value="RS"]').click()
sleep(1)
driver.find_element_by_css_selector('[placeholder="Cidade"]').send_keys('porto alegre')
sleep(1)
driver.find_element_by_xpath('//button[@value="Porto Alegre"]').click()
sleep(2)
driver.find_element_by_class_name('btn').click()

Então após resolver o captcha manualmente eu executei a segunda parte do código:

from bs4 import BeautifulSoup

soup = BeautifulSoup(driver.page_source)
results = soup.findAll('div', {'class': 'content-result'})

pessoas = []

for item in results:
    p = {}
    p['name'] = item.find('h1').getText()
    p['phone'] = item.find('p').getText().replace(' Telefone: ', '')
    p['address'] = item.findAll('p')[1].getText().replace(' Endereço:  ', '')

    pessoas.append(p)

pessoas

hmm entendi, pensei que você tinha puxado dentro do captcha . Mas eu estava pensando em uma rede neuras, você acha que pode dar certo?

Sinceramente não sei dizer se pode funcionar, basicamente a gente está tentando superar o Google ao tentar burlar o recaptcha.

Entendo, obrigado.

o get rid of this warning, pass the additional argument 'features="html.parser"' to the BeautifulSoup constructor.

  soup = BeautifulSoup(driver.page_source)

está me dando esse erro no seu codigo

Adiciona esse parser que ele informou no erro que deve desaparecer o warning:

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