web-dev-qa-db-fra.com

Le contenu de la page est chargé avec JavaScript et Jsoup ne le voit pas

Un bloc de la page est rempli de contenu par JavaScript et, après le chargement de la page avec Jsoup, aucune information de ce type n’a été trouvée. Existe-t-il un moyen d’obtenir également du contenu généré par JavaScript lors de l’analyse de page avec Jsoup?

Impossible de coller le code de page ici, car il est trop long: http://Pastebin.com/qw4Rfqgw

Voici l'élément dont j'ai besoin: <div id='tags_list'></div>

J'ai besoin d'obtenir cette information en Java. De préférence en utilisant Jsoup. L'élément est un champ avec l'aide de JavaScript:

<div id="tags_list">
    <a href="/tagsc0t20099.html" style="font-size:14;">разведчик</a>
    <a href="/tagsc0t1879.html" style="font-size:14;">Sr</a>
    <a href="/tagsc0t3140.html" style="font-size:14;">стратегический</a>
</div>

Code 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();
        }
    }
}
24
Eugene

JSoup est un analyseur syntaxique HTML, et non une sorte de moteur de navigateur intégré. Cela signifie qu'il ignore totalement le contenu ajouté au DOM par Javascript après le chargement initial de la page.

Pour avoir accès à ce type de contenu, vous aurez besoin d'un composant de navigateur intégré, plusieurs discussions ont eu lieu sur SO concernant ce type de composant, par exemple Y a-t-il un moyen d'intégrer un navigateur en Java?

21
fvu

Résolu dans mon cas avec com.codeborne.phantomjsdriver NOTE: c'est du code groovy.

pom.xml

        <dependency>
          <groupId>com.codeborne</groupId>
          <artifactId>phantomjsdriver</artifactId>
          <version> <here goes last version> </version>
        </dependency>

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))
13
iluhin

Vous devez comprendre ce qui se passe:

  • Lorsque vous interrogez une page d'un site Web, que vous utilisiez Jsoup ou votre navigateur, du HTML vous est renvoyé. Jsoup est capable d'analyser cela.
  • Cependant, la plupart des sites Web incluent Javascript dans ce code HTML ou un lien à partir de ce code HTML, qui remplira la page de contenu. Votre navigateur est capable d'exécuter le Javascript, et donc de remplir la page. Jsoup n'est pas.

La façon de comprendre ceci est la suivante: l'analyse du code HTML est simple. L'exécution du code Javascript et la mise à jour du code HTML correspondant sont beaucoup plus complexes et constituent le travail d'un navigateur.

Voici quelques solutions à ce type de problèmes:

  1. Si vous pouvez trouver quels sont les appels Ajax effectués par le code Javascript, c'est-à-dire le chargement de contenu, vous pourrez peut-être utiliser l'URL de ces appels avec Jsoup. Pour ce faire, utilisez les outils de développement de votre navigateur. Mais cela n'est pas garanti pour fonctionner:

    • il se peut que l'URL soit dynamique et dépende de ce qui se trouve sur la page à ce moment-là
    • si le contenu n'est pas public, des cookies seront impliqués et une simple interrogation de l'URL de la ressource ne suffira pas
  2. Dans ces cas, vous devrez "simuler" le travail d'un navigateur. Heureusement, de tels outils existent. Celui que je connais et que je recommande est PhantomJS . Cela fonctionne avec Javascript, et vous auriez besoin de le lancer à partir de Java en lançant un nouveau processus. Si vous souhaitez vous en tenir à Java, cet article répertorie certaines alternatives Java.

4
Vic Seedoubleyew

J'ai fait il y a un "chemin"! Il s’agit peut-être plus d’une solution de contournement que d’une "manière ... Le code ci-dessous vérifie à la fois le méta-attribut" REFRESH "et les redirections javascript ... Si l’un d’eux existe, la variable RedirectedUrl est définie. Vous connaissez donc votre cible ... Ensuite, vous pouvez récupérer la page cible et continuer ...

    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...
1
salihcenap

Après avoir spécifié l'agent utilisateur, mon problème est résolu.

https://github.com/jhy/jsoup/issues/287#issuecomment-12769155

0
emon

Existe-t-il un moyen d'obtenir également du contenu généré par javascript lors de l'analyse d'une page avec Jsoup?

Je vais deviner NON, en pensant à la difficulté que cela pourrait être, sans construire un interpréteur javascript complet en Java.

0
James