Содержимое страницы загружается с помощью 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();
}
}
}
Ответы
Ответ 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.
Ответ 6
После указания агента пользователя моя проблема решена.
https://github.com/jhy/jsoup/issues/287#issuecomment-12769155
Ответ 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();