Подтвердить что ты не робот

Содержимое страницы загружается с помощью JavaScript, и Jsoup не видит его

Один блок на странице заполнен содержимым 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();
        }
    }
}
4b9b3361

Ответ 1

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

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

Ответ 2

Решено в моем случае с com.codeborne.phantomjsdriver ПРИМЕЧАНИЕ: это код 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))

Ответ 3

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

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

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

Вот некоторые решения для таких проблем:

  • Если вы можете узнать, какие вызовы Ajax, которые обрабатывает Javascript, загружает контент, вы можете использовать URL-адрес этих вызовов с помощью Jsoup. Для этого используйте средства разработчика в своем браузере. Но это не гарантируется:

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

Ответ 4

Я факт, что есть "путь"! Возможно, это более "обходной путь", чем "способ...". В приведенном ниже коде проверяются как мета-атрибуты "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...

Ответ 5

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

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

Ответ 7

Try:

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