Wie lade ich programmgesteuert eine Webseite in Java herunter?

116

Ich möchte in der Lage sein, das HTML einer Webseite abzurufen und in einem zu speichern String, damit ich etwas daran verarbeiten kann. Wie könnte ich mit verschiedenen Arten der Komprimierung umgehen?

Wie würde ich das mit Java machen?

jjnguy
quelle
Dies ist im Grunde ein Sonderfall von stackoverflow.com/questions/921262/…
Robin Green

Antworten:

110

Hier ist ein getesteter Code, der die URL- Klasse von Java verwendet . Ich würde jedoch empfehlen, die Ausnahmen besser zu behandeln als hier, oder sie an den Aufrufstapel weiterzuleiten.

public static void main(String[] args) {
    URL url;
    InputStream is = null;
    BufferedReader br;
    String line;

    try {
        url = new URL("http://stackoverflow.com/");
        is = url.openStream();  // throws an IOException
        br = new BufferedReader(new InputStreamReader(is));

        while ((line = br.readLine()) != null) {
            System.out.println(line);
        }
    } catch (MalformedURLException mue) {
         mue.printStackTrace();
    } catch (IOException ioe) {
         ioe.printStackTrace();
    } finally {
        try {
            if (is != null) is.close();
        } catch (IOException ioe) {
            // nothing to see here
        }
    }
}
Bill die Eidechse
quelle
16
DataInputStream.readLine () ist veraltet, aber abgesehen von diesem sehr guten Beispiel. Ich habe einen InputStreamReader () verwendet, der in einen BufferedReader () eingeschlossen ist, um die Funktion readLine () abzurufen.
mjh2007
2
Dies berücksichtigt nicht die Zeichenkodierung. Während es für ASCII-Text zu funktionieren scheint, führt es schließlich zu "seltsamen Zeichen", wenn eine Nichtübereinstimmung vorliegt.
Artbristol
In der 3. Zeile ersetzen DataInputStreamdurch BufferedReader. Und ersetzen Sie "dis = new DataInputStream(new BufferedInputStream(is));"zu"dis = new BufferedReader(new InputStreamReader(is));"
kolobok
1
@akapelko Danke. Ich habe meine Antwort aktualisiert, um die Aufrufe veralteter Methoden zu entfernen.
Bill the Lizard
2
was ist mit dem Schließen der InputStreamReader?
Alexander - Reinstate Monica
170

Ich würde einen anständigen HTML-Parser wie Jsoup verwenden . Es ist dann so einfach wie:

String html = Jsoup.connect("http://stackoverflow.com").get().html();

Es verarbeitet GZIP- und Chunked-Antworten sowie die Zeichencodierung vollständig transparent. Es bietet auch weitere Vorteile, wie das Durchlaufen und Bearbeiten von HTML durch CSS-Selektoren, wie es jQuery tun kann. Sie müssen es nur als Document, nicht als String.

Document document = Jsoup.connect("http://google.com").get();

Sie möchten wirklich keine grundlegenden String-Methoden ausführen oder sogar HTML-Dateien regulieren, um sie zu verarbeiten.

Siehe auch:

BalusC
quelle
3
Gute Antwort. Etwas verspätet. ;)
jjnguy
59
Besser als nie.
BalusC
Fantastische Bibliothek :) Danke dafür.
Jakub P.
Warum hat mir noch niemand von .html () erzählt? Ich habe mir sehr genau angesehen, wie man das von Jsoup abgerufene HTML einfach speichert, und das hilft sehr.
Avamander
Wenn Sie diese Bibliothek in Android für Neulinge verwenden, müssen Sie sie in einem anderen Thread verwenden, da sie standardmäßig auf demselben Anwendungsthread ausgeführt wird, wodurch die Anwendung NetworkOnMainThreadException
ausgelöst wird
24

Bills Antwort ist sehr gut, aber Sie möchten möglicherweise einige Dinge mit der Anfrage tun, wie z. B. Komprimierung oder Benutzeragenten. Der folgende Code zeigt, wie Sie verschiedene Arten der Komprimierung Ihrer Anforderungen durchführen können.

URL url = new URL(urlStr);
HttpURLConnection conn = (HttpURLConnection) url.openConnection(); // Cast shouldn't fail
HttpURLConnection.setFollowRedirects(true);
// allow both GZip and Deflate (ZLib) encodings
conn.setRequestProperty("Accept-Encoding", "gzip, deflate");
String encoding = conn.getContentEncoding();
InputStream inStr = null;

// create the appropriate stream wrapper based on
// the encoding type
if (encoding != null && encoding.equalsIgnoreCase("gzip")) {
    inStr = new GZIPInputStream(conn.getInputStream());
} else if (encoding != null && encoding.equalsIgnoreCase("deflate")) {
    inStr = new InflaterInputStream(conn.getInputStream(),
      new Inflater(true));
} else {
    inStr = conn.getInputStream();
}

Um auch den Benutzeragenten festzulegen, fügen Sie den folgenden Code hinzu:

conn.setRequestProperty ( "User-agent", "my agent name");
jjnguy
quelle
Informationen zum Konvertieren des InputStream in einen String finden Sie in dieser Antwort .
SSight3
12

Nun, Sie könnten mit den eingebauten Bibliotheken wie URL und URLConnection arbeiten , aber sie geben nicht viel Kontrolle.

Persönlich würde ich mit der Apache HTTPClient- Bibliothek gehen.
Bearbeiten: HTTPClient wurde von Apache auf Lebensende gesetzt. Der Ersatz lautet: HTTP-Komponenten

Jon Skeet
quelle
Es gibt keine Java-Version von System.Net.WebRequest?
FlySwat
1
Irgendwie wäre das eine URL. :-) Zum Beispiel: neue URL (" google.com"). OpenStream () // => InputStream
Daniel Spiewak
1
@ Jonathan: Was Daniel größtenteils gesagt hat - obwohl WebRequest Ihnen mehr Kontrolle als URL gibt. HTTPClient ist in der Funktionalität näher, IMO.
Jon Skeet
9

Bei allen oben genannten Ansätzen wird der Webseitentext nicht so heruntergeladen, wie er im Browser angezeigt wird. Heutzutage werden viele Daten über Skripte in HTML-Seiten in Browser geladen. Keine der oben genannten Techniken unterstützt Skripte. Sie laden nur den HTML-Text herunter. HTMLUNIT unterstützt die Javascripts. Wenn Sie also den Webseitentext so herunterladen möchten, wie er im Browser angezeigt wird, sollten Sie HTMLUNIT verwenden .

user3690910
quelle
1

Sie müssten höchstwahrscheinlich Code von einer sicheren Webseite (https-Protokoll) extrahieren. Im folgenden Beispiel wird die HTML-Datei in c: \ temp \ filename.html gespeichert. Viel Spaß!

import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.FileWriter;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.URL;

import javax.net.ssl.HttpsURLConnection;

/**
 * <b>Get the Html source from the secure url </b>
 */
public class HttpsClientUtil {
    public static void main(String[] args) throws Exception {
        String httpsURL = "https://stackoverflow.com";
        String FILENAME = "c:\\temp\\filename.html";
        BufferedWriter bw = new BufferedWriter(new FileWriter(FILENAME));
        URL myurl = new URL(httpsURL);
        HttpsURLConnection con = (HttpsURLConnection) myurl.openConnection();
        con.setRequestProperty ( "User-Agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:63.0) Gecko/20100101 Firefox/63.0" );
        InputStream ins = con.getInputStream();
        InputStreamReader isr = new InputStreamReader(ins, "Windows-1252");
        BufferedReader in = new BufferedReader(isr);
        String inputLine;

        // Write each line into the file
        while ((inputLine = in.readLine()) != null) {
            System.out.println(inputLine);
            bw.write(inputLine);
        }
        in.close(); 
        bw.close();
    }
}
QS-Spezialist
quelle
0

Auf einer Unix / Linux-Box könnten Sie einfach 'wget' ausführen, aber dies ist keine Option, wenn Sie einen plattformübergreifenden Client schreiben. Dies setzt natürlich voraus, dass Sie mit den heruntergeladenen Daten zwischen dem Herunterladen und dem Auftreffen auf die Festplatte nicht wirklich viel anfangen möchten.

Timo Geusch
quelle
Ich würde auch mit diesem Ansatz beginnen und ihn später umgestalten, wenn er nicht ausreicht
Dustin Getz
0

Jetty verfügt über einen HTTP-Client, mit dem eine Webseite heruntergeladen werden kann.

package com.zetcode;

import org.eclipse.jetty.client.HttpClient;
import org.eclipse.jetty.client.api.ContentResponse;

public class ReadWebPageEx5 {

    public static void main(String[] args) throws Exception {

        HttpClient client = null;

        try {

            client = new HttpClient();
            client.start();

            String url = "http://www.something.com";

            ContentResponse res = client.GET(url);

            System.out.println(res.getContentAsString());

        } finally {

            if (client != null) {

                client.stop();
            }
        }
    }
}

Das Beispiel druckt den Inhalt einer einfachen Webseite.

In einem Tutorial zum Lesen einer Webseite in Java habe ich sechs Beispiele für das Herunterladen einer Webseite programmgesteuert in Java unter Verwendung von URL, JSoup, HtmlCleaner, Apache HttpClient, Jetty HttpClient und HtmlUnit geschrieben.

Jan Bodnar
quelle
0

Holen Sie sich Hilfe von dieser Klasse, sie erhält Code und filtert einige Informationen.

public class MainActivity extends AppCompatActivity {

    EditText url;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate( savedInstanceState );
        setContentView( R.layout.activity_main );

        url = ((EditText)findViewById( R.id.editText));
        DownloadCode obj = new DownloadCode();

        try {
            String des=" ";

            String tag1= "<div class=\"description\">";
            String l = obj.execute( "http://www.nu.edu.pk/Campus/Chiniot-Faisalabad/Faculty" ).get();

            url.setText( l );
            url.setText( " " );

            String[] t1 = l.split(tag1);
            String[] t2 = t1[0].split( "</div>" );
            url.setText( t2[0] );

        }
        catch (Exception e)
        {
            Toast.makeText( this,e.toString(),Toast.LENGTH_SHORT ).show();
        }

    }
                                        // input, extrafunctionrunparallel, output
    class DownloadCode extends AsyncTask<String,Void,String>
    {
        @Override
        protected String doInBackground(String... WebAddress) // string of webAddress separate by ','
        {
            String htmlcontent = " ";
            try {
                URL url = new URL( WebAddress[0] );
                HttpURLConnection c = (HttpURLConnection) url.openConnection();
                c.connect();
                InputStream input = c.getInputStream();
                int data;
                InputStreamReader reader = new InputStreamReader( input );

                data = reader.read();

                while (data != -1)
                {
                    char content = (char) data;
                    htmlcontent+=content;
                    data = reader.read();
                }
            }
            catch (Exception e)
            {
                Log.i("Status : ",e.toString());
            }
            return htmlcontent;
        }
    }
}
Sohaib Aslam
quelle
0

Verwenden Sie dazu NIO.2 leistungsstarke Files.copy (InputStream in, Pfadziel):

URL url = new URL( "http://download.me/" );
Files.copy( url.openStream(), Paths.get("downloaded.html" ) );
Jan Tibar
quelle
-1

Ich habe die eigentliche Antwort auf diesen Beitrag ( URL ) verwendet und die Ausgabe in eine Datei geschrieben.

package test;

import java.net.*;
import java.io.*;

public class PDFTest {
    public static void main(String[] args) throws Exception {
    try {
        URL oracle = new URL("http://www.fetagracollege.org");
        BufferedReader in = new BufferedReader(new InputStreamReader(oracle.openStream()));

        String fileName = "D:\\a_01\\output.txt";

        PrintWriter writer = new PrintWriter(fileName, "UTF-8");
        OutputStream outputStream = new FileOutputStream(fileName);
        String inputLine;

        while ((inputLine = in.readLine()) != null) {
            System.out.println(inputLine);
            writer.println(inputLine);
        }
        in.close();
        } catch(Exception e) {

        }

    }
}
A_01
quelle