Il contenuto della pagina è caricato con javascript e Jsoup non lo vede

Un blocco sulla pagina è riempito di contenuto da javascript e dopo aver caricato la pagina con Jsoup non c’è nessuno di quei suggerimenti. C’è un modo per ottenere anche contenuti generati da javascript durante l’analisi della pagina con Jsoup ?

Speciale UPD per Marcin:
Imansible incollare il codice di pagina qui, poiché è troppo lungo: http://pastebin.com/qw4Rfqgw

Ecco l’elemento di cui ho bisogno:

Ho bisogno di ottenere queste informazioni in Java. Preferebaly usando Jsoup. L’elemento è campo con l’aiuto di javascript :

  

Codice Java:

 import org.jsoup.Jsoup; import org.jsoup.nodes.Document; import org.jsoup.nodes.Element; import org.jsoup.select.Elements; import java.io.IOException; public class Test { public static void main( String[] args ) { try { Document Doc = Jsoup.connect( "http://www.bestreferat.ru/referat-32558.html" ).get(); Elements Tags = Doc.select( "#tags_list a" ); for ( Element Tag : Tags ) { System.out.println( Tag.text() ); } } catch ( IOException e ) { e.printStackTrace(); } } } 

JSoup è un parser HTML , non una sorta di motore di browser incorporato. Ciò significa che è completamente inconsapevole di qualsiasi contenuto aggiunto al DOM da JavaScript dopo il caricamento iniziale della pagina.

Per accedere a quel tipo di contenuto è necessario un componente del browser incorporato, ci sono un certo numero di discussioni su SO per quel tipo di componente, ad esempio c’è un modo per incorporare un browser in Java?

Risolto nel mio caso con com.codeborne.phantomjsdriver NOTA: è un codice groovy.

pom.xml

   com.codeborne phantomjsdriver     

PhantomJsUtils.groovy

 import org.jsoup.Jsoup import org.jsoup.nodes.Document import org.openqa.selenium.WebDriver import org.openqa.selenium.phantomjs.PhantomJSDriver class PhantomJsUtils { private static String filePath = 'data/temp/'; public static Document renderPage(String filePath) { System.setProperty("phantomjs.binary.path", 'libs/phantomjs') // path to bin file. NOTE: platform dependent WebDriver ghostDriver = new PhantomJSDriver(); try { ghostDriver.get(filePath); return Jsoup.parse(ghostDriver.getPageSource()); } finally { ghostDriver.quit(); } } public static Document renderPage(Document doc) { String tmpFileName = "$filePath${Calendar.getInstance().timeInMillis}.html"; FileUtils.writeToFile(tmpFileName, doc.toString()); return renderPage(tmpFileName); } } 

ClassInProject.groovy

 Document doc = PhantomJsUtils.renderPage(Jsoup.parse(yourSource)) 

Devi capire cosa sta succedendo:

  • Quando si esegue una query su una pagina da un sito Web, sia che si utilizzi Jsoup o il browser, ciò che viene inviato all’utente è un codice HTML. Jsoup è in grado di analizzarlo.
  • Tuttavia, la maggior parte dei siti Web include Javascript in quel codice HTML o collegato da tale HTML, che popolerà la pagina con il contenuto. Il tuo browser è in grado di eseguire Javascript e quindi di compilare la pagina. Jsoup non lo è.

Il modo per capire questo è il seguente: analizzare il codice HTML è facile. L’esecuzione del codice Javascript e l’aggiornamento del corrispondente codice HTML sono molto più complessi ed è opera di un browser.

Ecco alcune soluzioni per questo tipo di problemi:

  1. Se riesci a trovare quali sono le chiamate Ajax eseguite dal codice Javascript, ovvero il caricamento del contenuto, potresti riuscire a utilizzare l’URL di tali chiamate con Jsoup. Per fare ciò, usa Strumenti per sviluppatori dal tuo browser. Ma questo non è garantito per funzionare:

    • potrebbe essere che l’url sia dinamico e dipende da cosa c’è nella pagina in quel momento
    • se il contenuto non è pubblico, i cookie saranno coinvolti e l’interrogazione dell’URL della risorsa non sarà sufficiente
  2. In questi casi, dovrai “simulare” il lavoro di un browser. Fortunatamente, questi strumenti esistono. Quello che conosco e consiglio è PhantomJS . Funziona con Javascript e avresti bisogno di avviarlo da Java avviando un nuovo processo. Se si desidera attenersi a Java, questo post elenca alcune alternative Java.

Io infatti c’è un “modo”! Forse è più un “rimedio” che un “modo … Il codice sotto controlla sia per il metaattore” REFRESH “che per i reindirizzamenti javascript … Se uno di essi esiste la variabile RedirectedUrl è impostata. Quindi conosci il tuo target … Quindi puoi recuperare la pagina di destinazione e andare avanti …

  String RedirectedUrl=null; Elements meta = page.select("html head meta"); if (meta.attr("http-equiv").contains("REFRESH")) { RedirectedUrl = meta.attr("content").split("=")[1]; } else { if (page.toString().contains("window.location.href")) { meta = page.select("script"); for (Element script:meta) { String s = script.data(); if (!s.isEmpty() && s.startsWith("window.location.href")) { int start = s.indexOf("="); int end = s.indexOf(";"); if (start>0 && end >start) { s = s.substring(start+1,end); s =s.replace("'", "").replace("\"", ""); RedirectedUrl = s.trim(); break; } } } } } ... now retrieve the redirected page again... 

C’è un modo per ottenere anche contenuti generati da javascript durante l’analisi della pagina con Jsoup?

Ho intenzione di indovinare NO, pensando a quanto sarebbe stato difficile, senza build un intero interprete javascript in Java.

Provare:

 Document Doc = Jsoup.connect(url) .header("Accept-Encoding", "gzip, deflate") .userAgent("Mozilla/5.0 (Windows NT 6.1; WOW64; rv:23.0) Gecko/20100101 Firefox/23.0") .maxBodySize(0) .timeout(600000) .get();