Como raspar um site javascript em Python?
Estou tentando raspar um site. Tentei usar dois métodos, mas ambos não me fornecem o código-fonte completo do site que estou procurando. Estou tentando extrair os títulos das notícias do URL do site fornecido abaixo.
URL: "https://www.todayonline.com/"
Esses são os dois métodos que tentei, mas falhei.
Método 1: bela sopa
tdy_url = "https://www.todayonline.com/"
page = requests.get(tdy_url).text
soup = BeautifulSoup(page)
soup # Returns me a HTML with javascript text
soup.find_all('h3')
### Returns me empty list []
Método 2: Selênio + BeautifulSoup
tdy_url = "https://www.todayonline.com/"
options = Options()
options.headless = True
driver = webdriver.Chrome("chromedriver",options=options)
driver.get(tdy_url)
time.sleep(10)
html = driver.page_source
soup = BeautifulSoup(html)
soup.find_all('h3')
### Returns me only less than 1/4 of the 'h3' tags found in the original page source
Por favor ajude. Eu tentei vasculhar outros sites de notícias e é muito mais fácil. Obrigado.
Respostas
Você pode acessar os dados via API (verifique a guia Rede):
Por exemplo,
import requests
url = "https://www.todayonline.com/api/v3/news_feed/7"
data = requests.get(url).json()
Existem diferentes maneiras de reunir o conteúdo de uma página da web que contém Javascript.
- Usando
seleniumo driver da web do Firefox - Usando um navegador sem cabeça com
phantomJS - Fazer uma chamada de API usando um cliente REST ou
requestsbiblioteca python
Você tem que fazer sua pesquisa primeiro
Vou sugerir a você uma abordagem bastante simples,
import requests
from bs4 import BeautifulSoup as bs
page = requests.get('https://www.todayonline.com/googlenews.xml').content
soup = bs(page)
news = [i.text for i in soup.find_all('news:title')]
print(news)
resultado
['DBS named world’s best bank by New York-based financial publication',
'Russia has very serious questions to answer on Navalny - UK',
"Exclusive: 90% of China's Sinovac employees, families took coronavirus vaccine - CEO",
'Three militants killed after fatal attack on policeman in Tunisia',
.....]
Além disso, você pode verificar a página XML para obter mais informações, se necessário.
PS Sempre verifique a conformidade antes de descartar qualquer site :)
Os dados de notícias no site que você está tentando copiar são obtidos do servidor usando JavaScript (isso é chamado de XHR - XMLHttpRequest ). Isso está acontecendo dinamicamente, enquanto a página está carregando ou sendo rolada. portanto, esses dados não são retornados dentro da página retornada pelo servidor.
No primeiro exemplo, você está recebendo apenas a página retornada pelo servidor - sem as notícias, mas com o JS que deve obtê-las. Nem as solicitações nem o BeautifulSoup podem executar JS.
No entanto, você pode tentar reproduzir solicitações que estão obtendo títulos de notícias do servidor com solicitações Python. Execute as seguintes etapas:
- Abra DevTools do seu navegador (normalmente você tem que pressionar F12ou Ctrl+ Shit+ Ipara isso) e dê uma olhada nas solicitações que estão obtendo títulos de notícias do servidor. Às vezes, é ainda mais fácil do que web scraping com BeautifulSoup. Aqui está uma captura de tela (Firefox):
Copie o link de solicitação (clique com o botão direito -> Copiar -> Copiar link) e passe-o para
requests.get(...).Saia
.json()do pedido. Ele retornará um dict que é fácil de trabalhar. Para entender melhor a estrutura do dicionário, eu recomendaria usar empprintvez da impressão simples. Observe que você deve fazerfrom pprint import pprintantes de usá-lo.
Aqui está um exemplo do código que obtém os títulos das principais notícias da página:
import requests
nodes = requests.get("https://www.todayonline.com/api/v3/news_feed/7")\
.json()["nodes"]
for node in nodes:
print(node["node"]["title"])
Se você quiser raspar um grupo de notícias sob legenda, você precisa alterar o número após news_feed/na URL de solicitação (para obtê-lo, você só precisa filtrar as solicitações por "news_feed" no DevTools e rolar a página de notícias para baixo).
Às vezes, os sites têm proteção contra bots (embora o site que você está tentando copiar não tenha). Nesses casos, você também pode precisar executar essas etapas .