Come raschiare un sito Web javascript in Python?

Sep 06 2020

Sto cercando di raschiare un sito web. Ho provato a utilizzare due metodi, ma entrambi non mi forniscono il codice sorgente completo del sito Web che sto cercando. Sto cercando di estrarre i titoli delle notizie dall'URL del sito Web fornito di seguito.

URL: "https://www.todayonline.com/"

Questi sono i due metodi che ho provato ma non sono riusciti.

Metodo 1: bella zuppa

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 []

Metodo 2: Selenio + 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 

Per favore aiuto. Ho provato a raschiare altri siti Web di notizie ed è molto più semplice. Grazie.

Risposte

2 politicalscientist Sep 06 2020 at 15:38

Puoi accedere ai dati tramite API (controlla la scheda Rete):


Per esempio,

import requests
url = "https://www.todayonline.com/api/v3/news_feed/7"
data = requests.get(url).json()
2 Noname Sep 06 2020 at 15:39

Esistono diversi modi per raccogliere il contenuto di una pagina web che contiene Javascript.

  1. Utilizzo seleniumcon il driver web di Firefox
  2. Utilizzando un browser headless con phantomJS
  3. Effettuare una chiamata API utilizzando un client REST o una requestslibreria python

Devi prima fare la tua ricerca

2 MananGajjar Sep 06 2020 at 16:04

Ti suggerirò l'approccio abbastanza semplice,

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)

produzione

['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',
.....]

Inoltre, è possibile controllare la pagina XML per ulteriori informazioni, se necessario.

PS Verificare sempre la conformità prima di rottamare qualsiasi sito Web :)

2 DemianWolf Sep 06 2020 at 16:00

I dati delle notizie sul sito Web che stai tentando di raccogliere vengono recuperati dal server utilizzando JavaScript (questo è chiamato XHR - XMLHttpRequest ). Sta accadendo dinamicamente, mentre la pagina si carica o si scorre. quindi questi dati non vengono restituiti all'interno della pagina restituita dal server.

Nel primo esempio, stai ottenendo solo la pagina restituita dal server - senza le notizie, ma con JS che dovrebbe ottenerle. Né le richieste né BeautifulSoup possono eseguire JS.

Tuttavia, puoi provare a riprodurre le richieste che ricevono titoli di notizie dal server con richieste Python. Procedi nel seguente modo:

  1. Apri DevTools del tuo browser (di solito devi premere F12o Ctrl+ Shit+ Iper quello) e dai un'occhiata alle richieste che stanno ricevendo titoli di notizie dal server. A volte, è anche più facile del web scraping con BeautifulSoup. Ecco uno screenshot (Firefox):
  1. Copia il link della richiesta (fai clic con il tasto destro -> Copia -> Copia link) e passalo a requests.get(...).

  2. Ottieni .json()la richiesta. Restituirà un dict con cui è facile lavorare. Per comprendere meglio la struttura del dict, consiglierei di utilizzare al pprintposto della semplice stampa. Nota che devi fare from pprint import pprintprima di usarlo.

Ecco un esempio del codice che ricava i titoli dalle principali notizie nella pagina:

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 vuoi racimolare un gruppo di notizie sotto didascalia, devi cambiare il numero dopo news_feed/nell'URL della richiesta (per ottenerlo, devi solo filtrare le richieste per "news_feed" nei DevTools e scorrere la pagina delle notizie verso il basso).

A volte i siti web sono protetti contro i bot (sebbene il sito web che stai cercando di raschiare non lo sia). In questi casi, potrebbe essere necessario eseguire anche questi passaggi .