IMDB Name und Bewertung auslesen

JavaNase

Mitglied
Hallo Leute,

ich und mein Studienpartner verzweifeln gerade regelrecht an der gestellten Aufgabe "HTML Knoten mit Eclipse auslessen bzw crawlen zu lassen". Vorweg schon mal entschuldigung, wenn wir hier irgendwelche falschen bzw nicht gängigen Formatierungen benutzen.

Wir haben uns als Ziel gesetzt bei der Internetseite "http://www.imdb.de/title/tt1637725/" den Namen des Films und die Bewertung crawlen zu lassen. In diesem Fall wäre das "Ted" und "7.6".

Wir benutzen dafür 3 Klasse deren Code entsprechen aussieht ...

Der Code für unseren simpleController sieht so aus

Java:
import edu.uci.ics.crawler4j.crawler.CrawlController;

	/**
	 * @author Yasser Ganjisaffar <yganjisa at uci dot edu>
	 */

	public class simpleController {

			public static void main(String[] args) throws Exception {
				if (args.length < 2) {
					System.out.println("Please specify 'root folder' and 'number of crawlers'.");
					return;
				}
				
				/*
				 * rootfolder is a folder where intermediate crawl data is
				 * stored. 
				 */
				String rootFolder = args[0];
				
				/*
				 * numberOfCrawlers shows the number of concurrent threads
				 * that should be initiated for crawling.
				 */
				int numberOfCrawlers = Integer.parseInt(args[1]);
				
				/*
				 * Instantiate the controller for this crawl. Note that if you want
				 * your crawl to be resumable (meaning that you can resume the crawl
				 * from a previously interrupted/crashed crawl) you can either set
				 * crawler.enable_resume to true in crawler4j.properties file or you
				 * can use the second parameter to the CrawlController constructor.
				 * 
				 * Note: if you enable resuming feature and want to start a fresh
				 * crawl, you need to delete the contents of rootFolder manually.
				 */
				CrawlController controller = new CrawlController(rootFolder);
				
				/*
				 * For each crawl, you need to add some seed urls.
				 * These are the first URLs that are fetched and
				 * then the crawler starts following links which
				 * are found in these pages
				 */
				// controller.addSeed("http://www.lamberti-apotheke-hildesheim.de/");
				controller.addSeed("http://www.imdb.de/title/tt0120338/");
				// controller.addSeed("http://www.bild.de/");
				
				/*
				 * Be polite:
				 * Make sure that we don't send more than 5 requests per 
				 * second (200 milliseconds between requests).
				 */
				controller.setPolitenessDelay(200);
				
				/*
				 * Optional:
				 * You can set the maximum crawl depth here.
				 * The default value is -1 for unlimited depth
				 */
				controller.setMaximumCrawlDepth(3);
				
				/*
				 * Optional:
				 * You can set the maximum number of pages to crawl.
				 * The default value is -1 for unlimited depth
				 */
				controller.setMaximumPagesToFetch(50);
				
				/*
				 * Do you need to set a proxy?
				 * If so, you can use: 
				 * controller.setProxy("proxyserver.example.com", 8080);
				 * OR
				 * controller.setProxy("proxyserver.example.com", 8080, username, password);
				 */
				
				/*
				 * Note: you can configure several other parameters by modifying 
				 * crawler4j.properties file
				 */
				
				/*
				 * Start the crawl. This is a blocking operation, meaning
				 * that your code will reach the line after this only when
				 * crawling is finished.
				 */
				System.out.println("Crawl starting ... ");

				controller.start(theCrawlerAnalyzer.class, numberOfCrawlers);
				
				System.out.println("Crawl ready");
			}


}

Code für den theCrawler

Java:
import java.util.regex.Pattern;

import edu.uci.ics.crawler4j.crawler.Page;
import edu.uci.ics.crawler4j.crawler.WebCrawler;
import edu.uci.ics.crawler4j.url.WebURL;

import java.util.List;

public class theCrawler extends WebCrawler {

        Pattern filters = Pattern.compile(".*(\\.(css|js|bmp|gif|jpe?g"  + "|png|tiff?|mid|mp2|mp3|mp4"  + "|wav|avi|mov|mpeg|ram|m4v|pdf"  + "|rm|smil|wmv|swf|wma|zip|rar|gz))$");

        /*
         * 
         * You should implement this function to specify
         * whether the given URL should be visited or not.
         */
        public boolean shouldVisit(WebURL url) {
                String href = url.getURL().toLowerCase();
                if (filters.matcher(href).matches()) {
                        return false;
                }
                if (href.startsWith("http")) {
                        return true;
                }
                return false;
        }

        /*
         * This function is called when a page is fetched
         * and ready to be processed by your program
         */
        
        public void visit(Page page) {
                int docid = page.getWebURL().getDocid();
                String url = page.getWebURL().getURL();         
                String text = page.getText();
                List<WebURL> links = page.getURLs();   
                
                System.out.println ("\nNew URL"); 
                System.out.println (docid);
                
                if (text.contains("Titanic") && url.contains("tt1735898") )  
                {
                // System.out.println (text);
                System.out.println (url);
                System.out.println ("Anzahl der Links: "+ links.size());
                System.out.println ("Länge Text"+ text.length());
                String snippet = "";
                snippet = text.substring(text.indexOf("Titanic"), text.indexOf("Titanic")+30);
                snippet = snippet.trim();
                System.out.println (snippet);
        		}	
        }

}

Code für den theCrawlerAnalyzer

Java:
import java.util.regex.Pattern;
import java.util.Vector;
import org.w3c.dom.Node;
import org.w3c.dom.Element;
import org.w3c.dom.Attr;
import org.w3c.dom.NodeList;
import org.w3c.dom.NamedNodeMap;

import java.io.StringReader; 

import edu.uci.ics.crawler4j.crawler.Page;
import edu.uci.ics.crawler4j.crawler.WebCrawler;
import edu.uci.ics.crawler4j.url.WebURL;

import java.util.List;

import javax.swing.text.html.HTML.Attribute;

import org.cyberneko.html.parsers.DOMParser;
import org.xml.sax.InputSource; 


public class theCrawlerAnalyzer extends WebCrawler {

	Pattern filters = Pattern.compile(".*(\\.(css|js|bmp|gif|jpe?g"  + "|png|tiff?|mid|mp2|mp3|mp4"  + "|wav|avi|mov|mpeg|ram|m4v|pdf"  + "|rm|smil|wmv|swf|wma|zip|rar|gz))$");

	/*
	 * You should implement this function to specify
	 * whether the given URL should be visited or not.
	 */

	public boolean shouldVisit(WebURL url) {
		String href = url.getURL().toLowerCase();
		if (filters.matcher(href).matches()) {
			return false;
		}
		if (href.startsWith("http")) {
			return true;
		}
		return false;
	}

	/*
	 * This function is called when a page is fetched
	 * and ready to be processed by your program
	 */

	public void visit(Page page) {
		int docid = page.getWebURL().getDocid();
		String url = page.getWebURL().getURL();         
		List<WebURL> links = page.getURLs();  

		System.out.println ("\nNew URL:  " + docid + " URL: "+ url + "  with  " + links.size()+ "  links");

		// HTML DOM

		DOMParser parser = new DOMParser();

		try {
			parser.parse(new InputSource( new StringReader (page.getHTML())));

			//System.out.println ("print DOM ");
			//print(parser.getDocument(), " ");
			// try und catch führt parsing aus

		} 
		catch (Exception e) {
			System.out.println ("Parse-Fehler in Klasse \n: ");
			System.out.println (e.getClass() ); 
			System.out.println ("\n: " + e.getMessage() );
			e.printStackTrace();
		}
		try {
			
		

			Vector<Element> elems = new Vector<Element> (); 
			extractElements(parser.getDocument().getDocumentElement() ,"TABLE",elems);
			System.out.println ("Nr of table  elements: " + elems.size());   

			Vector<Element> elems2 = new Vector<Element> (); 
			extractElements(parser.getDocument().getDocumentElement() ,"TR",elems2);
			System.out.println ("Nr of TR elements: " + elems2.size());   
			
			Vector<Element> aelems = new Vector<Element> (); 
			extractElements(parser.getDocument().getDocumentElement() ,"a",aelems);
			System.out.println ("Nr of Anchors elements: " + aelems.size());
			
			
			for (int f=0; f<aelems.size(); aelems.size())
			{
				NamedNodeMap aelem = aelems.elementAt(f).getAttributes();

				// Get number of attributes in the element
				if (aelems != null) {
					int numAttrs = aelem.getLength() ;

					// Process each attribute
					for (int i=0; i<numAttrs; i++) {
						//NodeList attrs;
						Attr attr = (Attr)aelem.item(i);

						// Get attribute name and value
						String attrName = attr.getNodeName();
						String attrValue = attr.getNodeValue();
	
						
						//
					if (attrName == "Nutzer-Bewertung:")
					{
					
						System.out.println (aelems.toString()); 
					}
					}
					}
				}
			}
				
		catch (Exception e)
		{
			System.out.println ("Parse-Fehler in Klasse \n: ");
			System.out.println (e.getClass() ); 
			System.out.println (e.getMessage() );
		}

	}


	public static void print(Node node, String indent) {
		//		String s = node.getNodeValue();
		//		if ((s != null)  && (s != "")  ) {

		System.out.println(indent +  "node.NodeValue: " + node.getNodeValue());
		System.out.println(indent +  "name: " + node.getClass().getName());
		System.out.println(indent +  "node.toString: " +  node.toString());
		System.out.println(indent +  "node.toNodeName: " + node.getNodeName());
		System.out.println(indent +  "node.NodeValue: " + node.getNodeValue());
		System.out.println("");

		// Get all the attributes of an element in a map
		NamedNodeMap attrs = node.getAttributes();

		// Get number of attributes in the element
		if (attrs != null) {
			int numAttrs = attrs.getLength();

			// Process each attribute
			for (int i=0; i<numAttrs; i++) {
				Attr attr = (Attr)attrs.item(i);

				// Get attribute name and value
				String attrName = attr.getNodeName();
				String attrValue = attr.getNodeValue();
				System.out.println (indent +  "attrName :" +attrName );
				System.out.println (indent +  "attrValue :" +attrValue);
				System.out.println ();

			}
		}
		Node child = node.getFirstChild();
		while (child != null) {
			print(child, indent + " ");
			child = child.getNextSibling();
		}
	}


	protected void extractElements(Element element, String type, Vector<Element> elementList) {
		// this should not happen !
		if (element==null) {
			return;
		}
		String name = element.getNodeName();
		if (name.equals(type)) {
			elementList.add(element);
		}

		// recursive travel through all childs
		NodeList childs = element.getChildNodes();

		for (int i=0; i<childs.getLength(); i++) {
			if (childs.item(i) instanceof Element) {
				extractElements((Element)childs.item(i),type,elementList);
			}
		}

	}
}

Wir wissen das wir lediglich die theCrawlerAnalyzer-Klasse entsprechend umschreiben müssen, jedoch wissen wir nicht wie genau. Das einzige was wir wissen ist wo wir die gewünschten Werte im HTML-Code finden. Jedoch nicht wie wir direkt auf die zugreifen können und wie wir es dann schlussendlich auslesen lassen können.

Quelltext

Der auszugebende Name befindet sich immer in der Überschrift <h1>...</h1>

Code:
<h1 xmlns="http://www.w3.org/1999/xhtml">
    
    
    Ted <span>(2012) <span class="pro-link"><a target="_blank" href="http://www.imdb.com/rg/maindetails-title/warp-link/title/tt1637725/">Mehr auf IMDb.com</a> »</span><span class="title-extra"/></span>
    
</h1>

Hier findet man den Wert für die Benutzer bewertung ...

Code:
<div xmlns="http://www.w3.org/1999/xhtml" class="info stars">
      <h5>Nutzer-Bewertung:</h5>

      <div class="starbar">
        <div class="outer">
          <div style="width: 152px;" class="inner" id="general-voting-stars"/>
          <div class="starbar-votes">
            <a class="s10" onclick="return vote(10)" href="vote?v=10;
...
...
...
          </div>

        </div>
      </div>
  
      <div class="starbar-meta">
       <b>7,6/10</b>                      
           
           
             <a class="tn15more" href="ratings">51.041 Stimmen</a> »
        
        
      </div>
    </div>

Wir sind echt stark überfragt wie man hier weiter dran arbeiten kann und könnten wirklich eure Hilfe gebrauchen. Vielen Dank!

LG M&M
 

Mujahiddin

Top Contributor
Alles was du machen musst ist den Quelltext der Seite lesen und ein Muster herauslesen:

Code:
<title>Ted (2012)</title>

Code:
<div class="starbar-meta">
        <b>7,6/10</b> 
           
           
           &nbsp;&nbsp;<a href="ratings" class="tn15more">51.041 Stimmen</a>&nbsp;&raquo;
        
        
      </div>

Darauf machst du ein Regexpattern und lässt es über die Seite laufen.
 

JavaNase

Mitglied
Erst einmal danke natürlich.

Wir müssen leider gestehen noch nie was von einem Regexpattern gehört zu haben und darüber hinaus wollten wir gerne wissen, ob sich dieses Pattern dann in der "theCrawlerAnalyzer-Klasse" entsprechend implementieren ließe? Wir müssen nämlich mit dem gegeben arbeiten.

Danke für jede weitere Hilfe.
 

Mujahiddin

Top Contributor
Ganz ehrlich, ich kenne mich mit deinem Konstrukt nicht aus und habe auch keinerlei HTML-Erfahrung.
Also bei deinem theCrawlerAnalyzer kann ich dir nicht helfen.
Ich sag mal so - Voraussetzung ist, dass du den gesamten Quelltext der URL als String hast (oder nur die 2 Schnipsel aus meinem vorigen Beitrag).
Dann wendest du ein Pattern auf diese an. Fertig.
Ich kann dir mal ein Codebeispiel geben:

Java:
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.net.URL;
import java.util.Objects;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

public class IMDBMovie {
	
	public final String title;
	public final int year;
	public final double rating;
	public final int votes;
	
	public IMDBMovie(String title, int releaseYear, double rating, int votes) {
		this.title = title;
		this.year = releaseYear;
		this.rating = rating;
		this.votes = votes;
	}
	
	private static String regex = "(?s)<title>(\\w+)\\((\\d+)\\)</title>.*?< *div +class *= *\"starbar-meta\" *>[.&&[^<]]*?<b>(\\d[,|.]\\d)/10</b>.*?<a +href=\".*?\" class=\".*?\">(\\d|.|,) .*?</a>";
	private static Pattern pattern = Pattern.compile( regex );
	
	public static IMDBMovie of(String source) {
		Matcher m = pattern.matcher( Objects.requireNonNull( source ) );
		if( m.find() ) {
			String title = m.group( 1 );
			int year = Integer.valueOf( m.group( 2 ) );
			double rating = Double.valueOf( m.group( 3 ).replace( ",", "." ) );
			int votes = Integer.valueOf( m.group( 4 ).replace( ",", "" ).replace( ".", "" ) );
			return new IMDBMovie( title, year, rating, votes );
		}
		return null;
	}
	
	@Override
	public String toString() {
		return title + " (" + year + ") - " + rating + "/10 (" + votes + " Stimmen)";
	}
	
	public static void main(String... args) throws Exception {
		BufferedReader reader = new BufferedReader( new InputStreamReader( new URL( "http://www.imdb.com/title/tt0068646" ).openStream() ) );
		String source = "";
		String line;
		while( ( line = reader.readLine() ) != null )
			source += line + "\n";
		System.out.println( IMDBMovie.of( source ) );
	}
}

Evtl. muss am Regex noch gearbeitet werden - ich bekomme dauernd Error 403 bei
Code:
URL#openStream()
Aber so ungefähr müsste das stimmen.
 

Mujahiddin

Top Contributor
Mit folgendem Code funktioniert's:

Java:
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.HttpURLConnection;
import java.net.URL;
import java.text.NumberFormat;
import java.util.Objects;
import java.util.regex.Matcher;
import java.util.regex.Pattern;


public class IMDBMovie {
	
	public final String title;
	public final int year;
	public final double rating;
	public final int votes;
	
	public IMDBMovie(String title, int releaseYear, double rating, int votes) {
		this.title = title;
		this.year = releaseYear;
		this.rating = rating;
		this.votes = votes;
	}
	
	private static final String regexEng = "(?si)<title>([\\w ]+) \\((\\d+)\\).*?</title>.*?<span itemprop=\"ratingValue\">([\\d\\.,]+)</span>.*?<span itemprop=\"ratingCount\">([\\d\\.,]+)</span>";
	private static final String regexDe = "(?s)<title>([\\w ]+) \\((\\d+)\\).*?</title>.*?<div class=\"starbar-meta\">.*?<b>([\\d\\.,]+)/10</b>.*?<a href=\".*?\" class=\".*?\">([\\d\\.,]+).*?</a>";
	
	@SuppressWarnings("serial")
	private static class InvalidURLException extends RuntimeException {
		
		private InvalidURLException() {
			super();
		}
		
		private InvalidURLException(String message) {
			super( message );
		}
	}
	
	private static IMDBMovie of(String source, String ext) {
		Pattern p;
		if( ext.equals( "com" ) )
			p = Pattern.compile( regexEng );
		else if( ext.equals( "de" ) )
			p = Pattern.compile( regexDe );
		else
			throw new InvalidURLException( "Extension is not supported. Only \"com\" and \"de\" are supported." );
		Matcher m = p.matcher( Objects.requireNonNull( source ) );
		if( m.find() ) {
			String title = m.group( 1 );
			int year = Integer.valueOf( m.group( 2 ) );
			double rating = Double.valueOf( m.group( 3 ).replace( ",", "." ) );
			int votes = Integer.valueOf( m.group( 4 ).replace( ",", "" ).replace( ".", "" ) );
			return new IMDBMovie( title, year, rating, votes );
		}
		return null;
	}
	
	public static IMDBMovie of(URL url) throws IOException {
		if( !url.getHost().startsWith( "www.imdb." ) )
			throw new InvalidURLException( "Only host \"www.imdb.*\" ist supported." );
		HttpURLConnection con = (HttpURLConnection) url.openConnection();
		con.addRequestProperty( "User-Agent", "Mozilla/4.76" );
		BufferedReader reader = new BufferedReader( new InputStreamReader( con.getInputStream() ) );
		String source = "";
		String line;
		while( ( line = reader.readLine() ) != null )
			source += line + "\n";
		String ext = url.getHost().substring( url.getHost().lastIndexOf( '.' ) + 1 );
		return of( source, ext );
	}
	
	public static IMDBMovie of(String url) throws IOException {
		return of( new URL( url ) );
	}
	
	@Override
	public String toString() {
		return title + " (" + year + ") - " + NumberFormat.getInstance().format( rating ) + "/10 (" + NumberFormat.getInstance().format( votes ) + " Stimmen)";
	}
	
	public static void main(String... args) throws Exception {
		System.out.println( IMDBMovie.of( "http://www.imdb.de/title/tt1637725/" ) );
	}
}
 

JavaNase

Mitglied
Wow, danke für die Arbeit! Jedoch muss ich sagen, dass bei Zeile 7 "import java.util.Objects;" immer ein Fehler (import ... cannot be resolved) angezeigt wird und damit Fehler in Zeile 49 auslöst. Vllt ist das aber nur ein sehr kleines Problem, dass nur blutige Java-Anfänger nicht sehen können.

und ließe sich diese Zeilen einmal genauer erklären.

Code:
"(?s)<title>([\\w ]+) \\((\\d+)\\).*?</title>.*?<div class=\"starbar-meta\">.*?<b>([\\d\\.,]+)/10</b>.*?<a href=\".*?\" class=\".*?\">([\\d\\.,]+).*?</a>";

Ich meine zu wissen, dass dies die Mustererkennung zum Auslesen des HTML-Codes ist. Jedoch verstehe ich z.B. nicht warum "([\\w ]+) \\((\\d+)\\).*?" geschrieben werden muss um den Titel auszulesen. Ebenso der Rest scheint in meinen Augen sehr schwer nachvollziehbar.

Danke im Voraus!
 

andreT

Aktives Mitglied
Und nicht zu viel Requests/Sekunde absetzen. Wenn die da mittloggen meldet sich nachher noch so'n Abmahn-Anwalts-Parasit wegen AGBs und so :D
 

JavaNase

Mitglied
Ich weiß mir immer noch nicht zu helfen ... in Zeile 7 kommt immer "import java.util.Objects;cannot be resolved". Frage mich wie ich diesen Fehler beheben kann.

Irgendwelche Vorschläge?
 
Ähnliche Java Themen
  Titel Forum Antworten Datum
G Name des aktuellen Programms Allgemeine Java-Themen 7
L Ist ein string ein erlaubter variabel name? Allgemeine Java-Themen 2
S Variable als Objekt Name Allgemeine Java-Themen 3
J Apache POI - No external workbook with name Allgemeine Java-Themen 5
Neumi5694 Task-Name unter Windows Allgemeine Java-Themen 4
1 Name Generator für Videos Allgemeine Java-Themen 1
E Webservice zur Konvertierung IBAN/BIC -> Bank Name Allgemeine Java-Themen 1
P Name der Parent Klasse abfragen Allgemeine Java-Themen 8
D Name eines Nicht-String Objekts ausgeben Allgemeine Java-Themen 4
S Name einer Musikdatei auslesen und ändern Allgemeine Java-Themen 8
J .txt erstellen, nach name der vorhergehenden txt Allgemeine Java-Themen 7
J Suche: Tool zum Auffinden gleichnamiger Klassen (Name und Package gleich) in unteschiedlichen JARs Allgemeine Java-Themen 5
P ActionListener / Label Name auslesen Allgemeine Java-Themen 2
S java -jar name.war. Wie Extraktionspfad umbiegen? Allgemeine Java-Themen 2
S [JUnit] Name von TestCase bekommen Allgemeine Java-Themen 4
D Passende Name für Methoden finden Allgemeine Java-Themen 3
Dit_ Registry, Preferences | Name des Knotens ändern. Allgemeine Java-Themen 2
E String name in class convertieren Allgemeine Java-Themen 4
E Variablen anderer Klassen auslesen (nur Name bekannt) Allgemeine Java-Themen 4
S Konstrukt Sinn, Zewck und Name Allgemeine Java-Themen 6
Ark Name für Funktion gesucht Allgemeine Java-Themen 5
D variabler Listen name Allgemeine Java-Themen 3
M Name der Swing Komponente Allgemeine Java-Themen 3
C Name einlesen und Programm starten Allgemeine Java-Themen 2
S "Guessed User name" bei Tomcat belegen Allgemeine Java-Themen 2
J Name eines Strings durch einen String festlegbar? Allgemeine Java-Themen 2
M Name von Wochentagen vergleichen Allgemeine Java-Themen 3
M Zugriff auf Objekt, Name in Variable Allgemeine Java-Themen 3
F Welcher Name? paintsXY(), isPaintXY(), isPaintingXY() . Allgemeine Java-Themen 4
V Objekt einer Klasse, deren Name nur als String vorhanden Allgemeine Java-Themen 4
D Name der Java-Applikation Allgemeine Java-Themen 2
A Class File zur Laufzeit laden ohne den Binary Name zu kennen Allgemeine Java-Themen 11
G jar-Name einer Klasse Allgemeine Java-Themen 9
O String übergeben ist name eines JTextField wie zugreifen Allgemeine Java-Themen 9
S Name der ausführenden jar-Datei abfragen Allgemeine Java-Themen 11
Y fehler: wrong name serverA Allgemeine Java-Themen 3
F Parameter Name herausfinden Allgemeine Java-Themen 25
H Package name aus Class-File auslesen Allgemeine Java-Themen 11
P Duplicate name in Manifest Allgemeine Java-Themen 6
J Name des aktuell aktiven Windows-Fensters abfragen? Allgemeine Java-Themen 4
T JUSB - Name des USB Endgerätes zurückgeben Allgemeine Java-Themen 2
L Systeminformationen (PC-Name und Kennwort) auslesen Allgemeine Java-Themen 9
B Name eines komischen Klassenkonstruktes Allgemeine Java-Themen 14
S Sortierung einer Collection nach dem Attribut "name&quo Allgemeine Java-Themen 3

Ähnliche Java Themen

Neue Themen


Oben