2017-04-10 2 views
0

Ich bin auf der Website http://www.flashscore.com/nhl/ und ich versuche, die Links der Tabelle "Heutige Matches" zu extrahieren.Warum HTML-Code unterscheidet sich beim Parsen von Website mit Jsoup als mit Browser

Ich versuche es mit dem folgenden Code, aber es funktioniert nicht Können Sie darauf hinweisen, wo der Fehler liegt?

final Document page = Jsoup 
    .connect("http://d.flashscore.com/x/feed/t_4_200_G2Op923t_1_en_1") 
    .cookie("_ga","GA1.2.47011772.1485726144") 
    .referrer("http://d.flashscore.com/x/feed/proxy-local") 
    .userAgent("Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/56.0.2924.87 Safari/537.36") 
    .header("X-Fsign", "SW9D1eZo") 
    .header("X-GeoIP", "1") 
    .header("X-Requested-With", "XMLHttpRequest") 
    .header("Accept" , "*/*") 
    .get(); 

for (Element game : page.select("table.hockey tr")) { 
Elements links = game.getElementsByClass("tr-first stage-finished"); 
for (Element link : links) { 
    String linkHref = link.attr("href"); 
    String linkText = link.text(); 
} 
} 

Um zu versuchen, es zu beheben, fing ich an, es zu debuggen. Es zeigt, dass wir die Seite bekommen (obwohl wir irgendwie komische HTML bekommen). Danach zeigte das Debugging, dass die for-Schleife nicht einmal startet. Ich habe versucht, die Seite zu ändern. Wählen Sie ("") Teil zu anderen (wie getElementByAttribute usw.), aber ich habe gerade angefangen, Web Scraping zu lernen, also muss ich mich mit diesen Methoden vertraut machen, um durch ein Dokument zu navigieren. Wie soll ich diese Daten extrahieren?

Antwort

2

Wie in Kommentaren gesagt, muss diese Website einige Javascript ausführen, um diese verknüpfbaren Elemente zu erstellen. Jsoup analysiert nur HTML, es wird kein JS ausgeführt und Sie sehen nicht die gleiche HTML-Quelle, wenn Sie von einem Browser kommen oder von Jsoup.

Sie müssen die Website so aufrufen, als ob Sie sie in einem echten Browser ausführen würden. Sie können das programmatisch mit WebDriver und Firefox tun.

Ich habe mit Ihrem Beispiel Website ausprobiert und funktioniert:

pom.xml

<project> 

<modelVersion>4.0.0</modelVersion> 
<groupId>com.test</groupId> 
<artifactId>test</artifactId> 
<version>1.0-SNAPSHOT</version> 
<build> 
    <plugins> 
    <plugin> 
    <groupId>org.apache.maven.plugins</groupId> 
    <artifactId>maven-compiler-plugin</artifactId> 
    <configuration> 
     <source>1.8</source> 
     <target>1.8</target> 
     </configuration> 
    </plugin> 
    </plugins> 
</build> 
<packaging>jar</packaging> 

<name>test</name> 
<url>http://maven.apache.org</url> 

<properties> 
    <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> 
</properties> 

<dependencies> 
    <dependency> 
    <groupId>org.seleniumhq.selenium</groupId> 
    <artifactId>selenium-firefox-driver</artifactId> 
    <version>2.43.0</version> 
    </dependency> 
</dependencies> 

</project> 

App.java

package com.test; 

import org.openqa.selenium.By; 
import org.openqa.selenium.WebDriver; 
import org.openqa.selenium.firefox.FirefoxDriver; 
import java.util.Collections; 
import java.util.List; 
import java.util.stream.Collectors; 

public class App { 

public static void main(String[] args) { 
    App app = new App(); 
    List<String> links = app.parseLinks(); 
    links.forEach(System.out::println); 
} 

public List<String> parseLinks() { 
    try { 
     WebDriver driver ; 
     // should download geckodriver https://github.com/mozilla/geckodriver/releases and set according your local file 
     System.setProperty("webdriver.firefox.marionette","C:\\apps\\geckodriver.exe"); 
     driver = new FirefoxDriver(); 
     String baseUrl = "http://www.flashscore.com/nhl/"; 

     driver.get(baseUrl); 

     return driver.findElement(By.className("hockey")) 
       .findElements(By.tagName("tr")) 
       .stream() 
       .distinct() 
       .filter(we -> !we.getAttribute("id").isEmpty()) 
       .map(we -> createLink(we.getAttribute("id"))) 
       .collect(Collectors.toList()); 

    } catch (Exception e) { 
     e.printStackTrace(); 
     return Collections.EMPTY_LIST; 
    } 
} 

private String createLink(String id) { 
    return String.format("http://www.flashscore.com/match/%s/#match-summary", extractId(id)); 
} 

private String extractId(String id) { 
    if (id.contains("x_4_")) { 
     id = id.replace("x_4_",""); 
    } else if (id.contains("g_4_")) { 
     id = id.replace("g_4_",""); 
    } 

    return id; 
} 
} 

Ausgang:

http://www.flashscore.com/match/f9MJJI69/#match-summary 
http://www.flashscore.com/match/zZCyd0dC/#match-summary 
http://www.flashscore.com/match/drEXdts6/#match-summary 
http://www.flashscore.com/match/EJOScMRa/#match-summary 
http://www.flashscore.com/match/0GKOb2Cg/#match-summary 
http://www.flashscore.com/match/6gLKarcm/#match-summary 
... 
... 

PS: Arbeiten mit Firefox Version 32.0 und Selenium 2.43.0. Es ist ein häufiger Fehler, eine nicht unterstützte Version zwischen Selenium und Firefox zu verwenden.

+0

Hi @ exoddues unterstützt, vielen Dank für Ihre Lösung, es funktioniert wie Charme. Kannst du mir auch sagen, wie es möglich ist, nur diejenigen herauszufiltern, die das heutige Datum haben? Lassen Sie uns also sagen, dass das heutige Datum die Variable 'String date' ist. Ich denke ich sollte '.filter()' irgendwie benutzen. –

+0

Auf den ersten Blick scheint, dass die heutigen Matches in einem Div mit id = "fscountry" platziert sind. Ein Weg wäre zum Beispiel ein Filter, der die tr Elemente in einem div mit der ID = "fscountry" bekommt. Versuchen Sie, anstelle der ersten beiden zu verwenden.findElement Aufrufe verwenden etwas wie .findElement (By.id ("fscountry")). findElements (By.tagName ("tr") – exoddus

+0

Hallo @exoddus, es war ein guter Tipp. Mit "fscountry" hat es nicht funktioniert, aber mit "fs". Wenn Sie die Elemente überprüfen, können Sie sehen, warum. In der Tabelle "Heutige Matches" gibt es immer zwei Elemente mit der gleichen ID (zwei Zeilen, das Heimteam oben, Auswärts Team unten), ich habe Dinge wie folgt geändert: ... .collections (toSet()) "also habe ich die gleiche ID nur einmal. Ich weiß nicht, ob es eine beste Lösung dafür ist, aber es funktioniert. –

0

Sie erhalten eine falsche Adresse in .connect("http://d.flashscore.com/x/feed/t_4_200_G2Op923t_1_en_1") - Sie müssen .connect("http://www.flashscore.com/nhl/") dort verwenden.

Dann verwendet diese Seite JS und nachdem Sie die richtige Seite bekommen-es wird anders gerendert als im Browser, z. Es wird keinen Tisch mit der Klasse "Hockey" geben. Du wirst es auf der Seite sehen, die du bekommen wirst. Sie müssen also Locators ändern. Oder überlegen Sie, WebDriver dafür zu verwenden.

+0

Sie haben Recht, ich habe die Zeichenfolge in der .connect geändert und jetzt bekomme ich das richtige HTML. Vielen Dank. :) und hast du eine Idee, wie ich die for-Schleife schreiben soll, um die Links der Spiele zu extrahieren? –

+0

Die Ergebnisse sind in 'div id =" Turnier-Seiten-Daten-Zusammenfassung-Ergebnisse "eingepackt, die keine Links enthalten. Ich denke nicht, dass es mit JSoup möglich ist. Versuchen Sie es mit einer 'WebDriver'-Implementation wie ChromeDriver oder FirefoxDriver - die JS –

Verwandte Themen