Содержимое страницы загружается с помощью JavaScript, а Jsoup его не видит - PullRequest
25 голосов
/ 20 сентября 2011

Один блок на странице заполнен содержимым с помощью JavaScript, и после загрузки страницы с помощью Jsoup такой информации не возникает.Есть ли способ получить также сгенерированный JavaScript контент при разборе страницы с Jsoup?

Не могу вставить сюда код страницы, так как он слишком длинный: http://pastebin.com/qw4Rfqgw

Вот элемент, которыйСодержание, которое мне нужно: <div id='tags_list'></div>

Мне нужно получить эту информацию на Java.Желательно с помощью Jsoup.Элемент является полем с помощью 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>

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

Ответы [ 7 ]

22 голосов
/ 20 сентября 2011

JSoup - это HTML парсер, а не какой-то встроенный движок браузера.Это означает, что он совершенно не знает о любом контенте, который добавляется в DOM с помощью Javascript после начальной загрузки страницы.

Чтобы получить доступ к этому типу контента, вам потребуется встроенный компонент браузера, существует рядобсуждения SO относительно такого рода компонента, например Есть ли способ встроить браузер в Java?

14 голосов
/ 07 сентября 2016

Решено в моем случае с com.codeborne.phantomjsdriver. ПРИМЕЧАНИЕ: это отличный код.

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))
5 голосов
/ 20 августа 2016

Вам нужно понять, что происходит:

  • Когда вы запрашиваете страницу на веб-сайте, будь то с помощью Jsoup или браузера, вам возвращается какой-то HTML. Jsoup может разобрать это.
  • Однако большинство веб-сайтов включают Javascript в этот HTML-код или ссылаются на этот HTML-код, который заполнит страницу контентом. Ваш браузер может выполнить Javascript и, таким образом, заполнить страницу. Jsoup нет.

Способ понять это заключается в следующем: парсинг HTML-кода прост. Выполнение кода Javascript и обновление соответствующего HTML-кода намного сложнее и является работой браузера.

Вот несколько решений для такого рода проблем:

  1. Если вы можете узнать, какие вызовы Ajax выполняет код Javascript, то есть загрузка контента, вы можете использовать URL этих вызовов с Jsoup. Чтобы сделать это, используйте Инструменты разработчика из вашего браузера. Но это не гарантирует работу:

    • Возможно, URL-адрес является динамическим и зависит от того, что находится на странице в то время
    • если контент не является общедоступным, будут задействованы файлы cookie, и простого запроса URL-адреса ресурса будет недостаточно
  2. В этих случаях вам необходимо будет «смоделировать» работу браузера. К счастью, такие инструменты существуют. Тот, кого я знаю и рекомендую, это PhantomJS . Он работает с Javascript, и вам нужно будет запустить его с Java, запустив новый процесс. Если вы хотите придерживаться Java, этот пост перечисляет некоторые альтернативы Java.

1 голос
/ 23 ноября 2013

Я на самом деле есть «путь»!Возможно, это скорее «обходной путь», чем «способ» ... Приведенный ниже код проверяет как метатрибут «REFRESH», так и перенаправления javascript ... Если какой-либо из них существует, установлена ​​переменная RedirectedUrl. Таким образом, вы знаете свою цель... Затем вы можете получить целевую страницу и продолжить ...

    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...
0 голосов
/ 06 декабря 2018

После указания пользовательского агента моя проблема решена.

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

0 голосов
/ 02 июля 2017

Попробуйте:

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();
0 голосов
/ 20 сентября 2011

Есть ли способ получить также сгенерированный javascript контент при разборе страницы с помощью Jsoup?

Я собираюсь угадать НЕТ, думая о том, насколько это будет сложно, без построения целогоинтерпретатор JavaScript в Java.

...