ページ上の1つのブロックはJavaScriptによってコンテンツで満たされ、Jsoupでページをロードした後、その情報はありません。 Jsoup
でページを解析するときにJavaScriptで生成されたコンテンツを取得する方法はありますか?
長すぎるため、ここにページコードを貼り付けることはできません: 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();
}
}
}
JSoupは[〜#〜] html [〜#〜]パーサーであり、何らかの組み込みブラウザエンジンではありません。つまり、最初のページの読み込み後にJavascriptによってDOMに追加されたコンテンツはまったく認識されません。
その種類のコンテンツにアクセスするには、埋め込みブラウザコンポーネントが必要になります。SOなど、その種類のコンポーネントに関して多くの議論があります。たとえば、 埋め込み方法はありますかJavaのブラウザ?
私の場合、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))
何が起こっているのかを理解する必要があります:
これを理解する方法は次のとおりです。HTMLコードの解析は簡単です。 Javascriptコードの実行と対応するHTMLコードの更新ははるかに複雑であり、ブラウザーの仕事です。
この種の問題の解決策は次のとおりです。
JavaScriptコードが行っているAjax呼び出し、つまりコンテンツの読み込みを見つけることができる場合、Jsoupでこれらの呼び出しのURLを使用できる可能性があります。そのためには、ブラウザから開発者ツールを使用します。しかし、これは動作することが保証されていません:
これらの場合、ブラウザの動作を「シミュレート」する必要があります。幸いなことに、そのようなツールが存在します。私が知っている、そしてお勧めするのは PhantomJS です。 Javascriptで動作し、新しいプロセスを開始してJavaから起動する必要があります。 Javaに固執したい場合は、 この投稿 にJavaの選択肢がいくつかリストされています。
実は「道」があるのです!多分それは「方法」よりも「回避策」です。以下のコードは、メタ属性「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...
ユーザーエージェントを指定した後、私の問題は解決しました。
https://github.com/jhy/jsoup/issues/287#issuecomment-12769155
Jsoupでページを解析するときにjavascriptで生成されたコンテンツを取得する方法はありますか?
Javaでjavascriptインタープリター全体を構築せずに、これがどれほど難しいかを考えながら、NOと推測します。