# Pdf Downloader



## kiril_valev (29. Aug 2008)

Hallo,
mein name ist kiril. ich bin student im 2 semester und versuche ein kleines prog auf die beine zu setzten. ich hoffe ich krieg nbisschen unterstützung, weil meine java skills noch nicht das gelbe vom Ei sind.

Folgendes:

Ein Programm, welches Suchmaschinen Ergebnisse auswertet und dann die links runterlädt. Mit links meine ich verlinkungen auf pdf-dateien(erstmal), vllt kommen später noch andere dazu.

Ich hab mir das so gedacht: 

Ein Objekt mit den Suchwörtern welches die verschiedenen URLs zusammenbastelt aus denen eine Suchabfrage besteht(google, yahoo, live altavista).

Danach wird der Quellcode der Seite runtergeladen und bearbeitet, sodass man am ende noch die links hat und die Anzahl der Suchergebnisse.

Mit der Anzahl der Suchergebnisse wird eine Schleife "gefüttert" welche die restlichen links für die Suche erstellt, damit man auf alle Seiten hat. Alles kommt in ein String[] oder ein HashSet(vllt besser wenn doppelte links angezeigt werden).

Die Strings werden dem Objekt FileDownloader übergeben, welcher die pdfs herunterlödt.

Was meint ihr? Wo könnten Probleme entstehen?

Ich hab schon selber ein Problem gefunden und vllt kan mir ja jmd helfen: wenn ich auf google zugreifen will mit connection.openConnection() und dann mit getInputStream() kommt ein 403(forbidden). Kann man das umgehen oder kennt ihr vllt eine suchmaschine, die die gleichen suchergebnisse liefert wie google?

Danke im voraus

Mit freundlichen grüßen
Kiril


----------



## musiKk (29. Aug 2008)

Das mit Google ist eine heikle Sache. Ich braeuchte das im Moment eigentlich auch, aber es gibt von Google per se keine Erlaubnis, automatisierte Services auf die Suche loszulassen und nach dem, was ich im Internet gelesen habe, greifen die auch mal schnell durch und blockieren Anfragen, wenn mans uebertreibt. Man koennte ueber die AJAX-Schnittstelle ran, das waere sehr leicht zu parsen, aber das ist rechtlich wohl alles sehr unguenstig. Gegen "immer mal ne Anfrage", wie man sie auch aus dem Browser taetigen wuerde, ist jedoch sicher nicht viel zu sagen.

Dein forbidden resultiert vermutlich aus dem user agent. Den kannst du mit addRequestProperty() (naja, man kann den Link sicher erkennen...) setzen. Der key lautet "user-agent" und als value musste dir einen aussuchen.


----------



## pc-world (29. Aug 2008)

Dafür empfehle ich von den Jakarta Commons den HttpClient.
Ich bin gerade auch dabei, ein Tutorial zu schreiben, wie man mit dem HttpClient arbeitet. Allerdings ist dieses noch nicht fertig, und "erklärt" wurde bis jetzt nur das hochladen von Dateien ins Internet. Wenn es dich trotzdem interessiert: http://www.java-forum.org/de/topic73835_notizzettel-tutorial-bilder-upload-jakarta-httpclient.html
_Sehr gut_ beschrieben finde ich den HttpClient unter http://www.theserverside.com/tt/articles/article.tss?l=HttpClient_FileUpload

Als erstes lädst du dir das Ding hier herunter: http://hc.apache.org/downloads.cgi, z. B. die commons-httpclient-3.1.zip.
Dann _commons-httpclient-3.1.jar_ aus dem Archiv in dein Projekt einbinden (wenn du mit Eclipse arbeitest, ist in meinem Tutorial beschrieben, wie das geht).

So ungefähr machst du dann eine Suchabfrage bei Google:


```
import org.apache.commons.httpclient.*;
import org.apache.commons.httpclient.methods.GetMethod;

public class GoogleSearch {

    public static void los() {
      new GoogleSearch().suche("http://www.google.de/search", "Test", "pdf", 100);
    }

    public void suche(String url, String suchbegriff, String dateiEndung /* z. B. "pdf", ohne Punkt davor */, int maxErgebnisse) {
                         //maxErgebnisse sollte nicht größer als 100 sein (bringt nichts)

        //Neuer HttpClient, kannst dir so wie nen Browser vorstellen
        HttpClient client = new HttpClient();

        //Neue GET-Methode
        HttpMethod method = new GetMethod(url);

        //Die ganzen Parameter, die in der URL übergeben werden
        NameValuePair nvp1= new NameValuePair("firstName","fname");
        NameValuePair nvp2= new NameValuePair("lastName","lname");
        NameValuePair nvp3= new NameValuePair("email","email@email.com");

        NameValuePair[] pairs = { new NameValuePair("as_q", suchbegriff), new NameValuePair("hl", "de"), new NameValuePair("num", maxErgebnisse.toString()), new NameValuePair("btnG", "Google-Suche"), new NameValuePair("as_epq", ""), new NameValuePair("as_oq", ""), new NameValuePair("lr", ""), new NameValuePair("cr", ""), new NameValuePair("cr", ""), new NameValuePair("as_ft", "i"), new NameValuePair("as_filetype", dateiEndung), new NameValuePair("as_qdr", "all"), new NameValuePair("as_occt", "any"), new NameValuePair("as_dt", "i"), new NameValuePair("as_sitesearch", ""), new NameValuePair("as_rights", ""), new NameValuePair("safe", "images") };

        method.setQueryString(pairs);

        try{
            client.executeMethod(method);

            
            String ausgabe = method.getResponseBodyAsString(); //Das ist der HTML-Code, den Google zurückgibt
            System.out.println("Ausgabe:\n" + ausgabe);

            //Verbindung schließen
            method.releaseConnection();
        }
        catch(IOException e) {
            e.printStackTrace();
        }
    }
}
```

Um dann die Links rauszusuchen, könnte der HTMLparser (http://htmlparser.sourceforge.net/) hilfreich sein, allerdings habe ich mit ihm noch nie gearbeitet.

Du kannst es auch selber machen, ungefähr nach diesem Prinzip: http://www.java-forum.org/de/viewtopic.php?t=73669

Musst dir halt mal den Quellcode von den Google-Suchergebnissen anschauen.

Gruß,
pc-world


----------



## kiril_valev (29. Aug 2008)

Sehr schön, danke für die Hilfe. Ich versuch dann mal was auf den monitor zu zaubern und meld mich dann wieder wenn ich probleme oder fragen hab.


----------



## pc-world (29. Aug 2008)

Hab den Code mal in Eclipse eingefügt, ein paar Syntaxfehler und so korrigiert und - hätte ich kaum gedacht - es funktioniert!

Hier nochmal der Code ohne die paar Fehler:


```
import java.io.IOException;

import org.apache.commons.httpclient.*;
import org.apache.commons.httpclient.methods.GetMethod;

public class GoogleSearch {

	public static void main(String[] args) {
		new GoogleSearch().suche("http://www.google.de/search", "Test", "pdf",
				100);
	}

	public void suche(String url, String suchbegriff, String dateiEndung /*
																		 * z. B.
																		 * "pdf"
																		 * ,
																		 * ohne
																		 * Punkt
																		 * davor
																		 */,
			int maxErgebnisse) {
		// maxErgebnisse sollte nicht größer als 100 sein (bringt nichts)

		// Neuer HttpClient, kannst dir so wie nen Browser vorstellen
		HttpClient client = new HttpClient();

		// Neue GET-Methode
		HttpMethod method = new GetMethod(url);

		// Die ganzen Parameter, die in der URL übergeben werden
		NameValuePair nvp1 = new NameValuePair("firstName", "fname");
		NameValuePair nvp2 = new NameValuePair("lastName", "lname");
		NameValuePair nvp3 = new NameValuePair("email", "email@email.com");

		NameValuePair[] pairs = { new NameValuePair("as_q", suchbegriff),
				new NameValuePair("hl", "de"),
				new NameValuePair("num", Integer.toString(maxErgebnisse)),
				new NameValuePair("btnG", "Google-Suche"),
				new NameValuePair("as_epq", ""),
				new NameValuePair("as_oq", ""), new NameValuePair("lr", ""),
				new NameValuePair("cr", ""), new NameValuePair("cr", ""),
				new NameValuePair("as_ft", "i"),
				new NameValuePair("as_filetype", dateiEndung),
				new NameValuePair("as_qdr", "all"),
				new NameValuePair("as_occt", "any"),
				new NameValuePair("as_dt", "i"),
				new NameValuePair("as_sitesearch", ""),
				new NameValuePair("as_rights", ""),
				new NameValuePair("safe", "images") };

		method.setQueryString(pairs);

		try {
			client.executeMethod(method);

			String ausgabe = method.getResponseBodyAsString(); // Das ist der
			// HTML-Code, den
			// Google zurückgibt
			System.out.println("Ausgabe:\n" + ausgabe);
		} catch (HttpException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}

		// Verbindung schließen
		method.releaseConnection();
	}
}
```


----------



## kiril_valev (29. Aug 2008)

cool, dankeschön. Nochmal eine Nachfrage wegen den post von musiKk, dass so eine Suche illegal ist. Stimmt das wirklich? Muss man sich da wegen irgendetwas Sorgen machen?


----------



## pc-world (29. Aug 2008)

kiril_valev hat gesagt.:
			
		

> cool, dankeschön. Nochmal eine Nachfrage wegen den post von musiKk, dass so eine Suche illegal ist. Stimmt das wirklich? Muss man sich da wegen irgendetwas Sorgen machen?



Naja... - Sorgen machen eigentlich nicht.
Es heißt zwar, man darf die Angebote von Google nur unter der von Google bereitgestellten Benutzeroberfläche benutzen.
Aber solange du da keine Bots betreibst, die 10 Abfragen pro Sekunde machen...

Und dass die dich anzeigen, kann ich mir auch kaum vorstellen - da müssten die doch Mitarbeiter bezahlen!
Aber da solche Fälle vermutlich tausende am Tag vorkommen, werden die - so meine Meinung - nichts machen.

Mehr als deine IP sperren werden sie nicht - und das aber auch nur - wenn du sehr viele Abfragen pro Sekunde machst.
Und einen Bot, der Google-Seiten durchsucht, willst du ja (hoffentlich) nicht erstellen!

*Rechtlicher Hinweis:*
Der Autor dieses Beitrags übernimmt keine Gewähr auf die Richtigkeit.
Er übernimmt keinerlei Haftung für auch nur irgendwas.


PS: Im letzten Satz hatte ich keine Lust zum "richtig" formulieren mehr, dass stimmt... ;-)


----------



## pc-world (29. Aug 2008)

Hier noch eine _ewiglange_ Diskussion über ähnliches: http://www.teltarif.de/forum/s27050/10-1.html
Dort geht es um Gspace, mit dem man GoogleMail als virtuelle Festplatte benutzen kann (aber das ist schon etwas mehr "verbrecherisch"... ;-))


----------



## musiKk (29. Aug 2008)

Ok, vielleicht kam mein Kommentar etwas zu drastisch. Wenn man immer mal ein paar Suchen startet, dann ist das sicher in Ordnung. Ich habe mal eben die "Terms of Service" ueberflogen und die andere Quelle, die ich im Netz gefunden hatte, war vielleicht ungenau oder veraltet. Jedenfalls heisst es hier:

_5.3 You agree not to access (or attempt to access) any of the Services by any means other than through the interface that is provided by Google, unless you have been specifically allowed to do so in a separate agreement with Google.
5.4 You agree that you will not engage in any activity that interferes with or disrupts the Services (or the servers and networks which are connected to the Services)._

Ich denke, beide Punkte "verbieten nicht", automatisierte Dienste zu verwenden.

Ich will nicht immer den Miesepeter spielen, aber bei solchen Dingen sollte man imho immer aufpassen.

Und natuerlich: _I am not a lawyer._


----------



## kiril_valev (29. Aug 2008)

ok, danke. Noch ne Frage zu meiner GUI wie kann ich in nem JFrame einen Button so implementieren, dass wenn man ihn drückt sich die Ordner Hierarchie meines PCs öffnet. Ziel ist es einen Ort auszuwählen in dem man die pdfs speichert.


----------



## pc-world (29. Aug 2008)

Über den _JFileChooser_:


```
JFileChooser fileChooser = new JFileChooser(deinJFrame);
fileChooser.showSaveDialog();
File woSollIchSpeichern = fileChooser.getSelectedFile();
```


----------



## pc-world (29. Aug 2008)

Das nicht jeder von neuem anfangen muss, wäre es nett, wenn du den Code, wenn du fertig bist, posten würdest (das mit der Google-Suche). Es gibt bestimmt einige, die das auch brauchen könnten.
Ich wäre auch bereit, ne kleine API zusammenzubasteln.

Wenn du Hilfe beim parsen brauchst - würde mich auch mal interessieren, die Such-Ergebnisse rauszufiltern.


----------



## kiril_valev (29. Aug 2008)

Danke
und
ok o werde code posten wenn was einigermaßen lauffähiges steht. aber bitte nicht lachen


----------



## pc-world (29. Aug 2008)

kiril_valev hat gesagt.:
			
		

> aber bitte nicht lachen



Bin doch selber Java-Anfänger!


----------



## pc-world (29. Aug 2008)

Für's parsen hab ich was auffälliges entdeckt, woran man die Suchergebnisse sehr gut von anderen Links unterscheiden kann.

1. Link von den Suchergebnissen:

```
[url="derLink"]derTitel[/url]
```

2. Link von den Suchergebnissen:

```
[url="derLink"]derTitel[/url]
```

Die Unterschiede:
- Link-URL und Titel (ist ja klar)
- Im onmousedown-Attribut steht immer folgendes:
return clk(this.href,'','','*Nummer des Suchergebnisses*','')

Und das Gute dabei ist: Wenn man jetzt auf Seite zwei von den Suchergebnissen geht, fängt das nicht wieder bei eins an - sondern setzt seine Nummerierung fort!

Google macht es uns doch wirklich einfach...


----------



## pc-world (29. Aug 2008)

Da man maximal 100 Suchergebnisse auf einer Seite haben kann, kann man noch den Parameter _start_ anhängen.

Wenn man 10 Such-Ergebnisse auf einer Seite sieht (Standard), ist der Wert von _start_ gleich 0.
Für die zweite Seite 10, für die dritte 20...

Das kommt dann auch zum _NameValuePair_-Array dazu.


----------



## kiril_valev (29. Aug 2008)

coole sache  ich hab da noch ne andere frage: gibts sowas wie "refresh" funktion für jframe? weil immer wenn ich meine frame starte dann ist zuerst alles grau. erst wenn man mit der maus das fenster einbisschen gößer macht oder es maximiert sieht man alle buttons, textfield etc.


----------



## pc-world (29. Aug 2008)

kiril_valev hat gesagt.:
			
		

> coole sache  ich hab da noch ne andere frage: gibts sowas wie "refresh" funktion für jframe? weil immer wenn ich meine frame starte dann ist zuerst alles grau. erst wenn man mit der maus das fenster einbisschen gößer macht oder es maximiert sieht man alle buttons, textfield etc.




```
deinJFrame.repaint();
```

bzw.


```
deinJPanel.repaint();
```

Gruß,
pcworld


----------



## kiril_valev (29. Aug 2008)

mit


```
getContentPane().validate()
```

hats gerade auch geklappt.


----------



## pc-world (29. Aug 2008)

kiril_valev hat gesagt.:
			
		

> mit
> 
> 
> ```
> ...



Ich hab den Unterschied dieser zwei Methoden bis heute nicht begriffen


----------



## pc-world (29. Aug 2008)

Nochmal zum parsen zurück:
Ich denke, am einfachsten ist es, wenn die Suchergebnisse von Hand geparst werden.

Ungefähr wie hier beschrieben: http://www.java-forum.org/de/viewtopic.php?p=439707#439707 (Link hatte ich vorher schonmal gepostet.


----------



## kiril_valev (10. Sep 2008)

Hallo.
Ich hab jetzt mal eine andere Frage:

Weiß jmd wie man eine PDF nach bestimmten Strings durchsucht? Oder kann ich eine PDF in einen String umwandeln?

mfg kiril


----------



## pc-world (10. Sep 2008)

kiril_valev hat gesagt.:
			
		

> Hallo.
> Ich hab jetzt mal eine andere Frage:
> 
> Weiß jmd wie man eine PDF nach bestimmten Strings durchsucht? Oder kann ich eine PDF in einen String umwandeln?
> ...



Guck dir mal http://www.tutorials.de/forum/java/75629-pdf-dateien-mit-java-lesen.html an!

Übrigens: http://www.google.de/search?hl=de&q=Java+PDF+lesen&btnG=Google-Suche&meta= ;-)


----------



## kiril_valev (11. Sep 2008)

hallo, danke dir.

den ersten link hab ich gestern schon ausprobiert aber da fliegen mir gleich mehrere exceptions um die ohren.
noch eine frage: pdf sind ja vektor graphiken soviel ich weiß. bei manchen kann man den text rauskopieren aber bei manchen gehts auch nicht. wieso ist das so? kann man ne pdf in xml oder postscript konvertieren um an der inhalt zu kommen?

EDIT: nochmal eine frage. Wie kann man mit dem HTMLEditorKit folgendes aus einer HTML rausfiltern:

```
<span class=ngrn>[url]www.uni-haifa.de/pdf/haifa_2_05.pdf[/url] </span>
```

ich will nur die url haben. wenn ich die html in nem String verwandle und dann den String durchsuche dauert das ziemlich lange iwie.

mfg kiril


----------



## pc-world (11. Sep 2008)

kiril_valev hat gesagt.:
			
		

> hallo, danke dir.
> 
> den ersten link hab ich gestern schon ausprobiert aber da fliegen mir gleich mehrere exceptions um die ohren.
> noch eine frage: pdf sind ja vektor graphiken soviel ich weiß. bei manchen kann man den text rauskopieren aber bei manchen gehts auch nicht. wieso ist das so? kann man ne pdf in xml oder postscript konvertieren um an der inhalt zu kommen?
> ...



Also in einen _String _würde ich das schon stecken.

Du könntest es mit folgendem probieren (ist halt en bisschen umständlich).
Bind davon ausgegangen, dass du mehrere solche span-Tags auslesen willst, und dass alle span-Tags mit der class ngrn einen Link enthalten.


```
import java.util.ArrayList;

public class SpanParser {

	public static void main(String[] args) {
		//Erstmal liest du deinen HTML-Code in einen String
		ArrayList<String> links = new ArrayList<String>();
		int nextIndex = 0;
		String html = "<span class=ngrn>[url]www.uni-haifa.de/pdf/haifa_2_05.pdf[/url] </span>";
		String spanTag = "<span class=ngrn>"; //Der span-Tag
		 String spanEnd = " </span>"; //Der "close"-span-Tag (wie auch immer man das nennt) - bin mal davon ausgegangen,
		           //dass das Leerzeichen vor </span> dazugehört
		while(true) {
		 
		 int indexOfSpanBegin = html.indexOf(spanTag, nextIndex) + spanTag.length() + 1; //Hier wird rausgelesen, wo der Link anfängt.
		 int indexOfSpanEnd = html.indexOf(spanEnd, indexOfSpanBegin) + 1; //das Link-Ende
		 
		 if(indexOfSpanBegin == -1) {
			 break;
		 }
		 nextIndex = indexOfSpanEnd + 2;
		 System.out.println(nextIndex);
		 
		 char[] urlChars = new char[indexOfSpanEnd - indexOfSpanBegin];
		 html.getChars(indexOfSpanBegin, indexOfSpanEnd, urlChars, 0);
		 String url = "";
		 for(char zeichen : urlChars) {
			 url += zeichen;
		 }
		 links.add(url);
		 
		 System.out.println(url);
		}
	}
}
```

Der Code hat noch nen kleinen Bug, dass er eine Endlosschleife macht und dann immer den ersten (=einzigen) Link ausgibt. Wie du wahrscheinlich siehst, hab ich versucht, ihn zu bekämpfen, find aber die entsprechende Schraube nicht! ;-)

Gruß,
pc-world


----------



## kiril_valev (12. Sep 2008)

Dankeschön,
man könnte auch mit einem StringTokenizer zählen wie oft der span tag vorkommt und dementsprechend die Schleife einrichten.


----------

