Come si scarica a livello di programmazione una pagina Web in Java


117

Vorrei essere in grado di recuperare l'html di una pagina web e salvarlo in un String, in modo da poter eseguire alcune elaborazioni su di esso. Inoltre, come posso gestire vari tipi di compressione.

Come potrei farlo usando Java?


Questo è fondamentalmente un caso speciale di stackoverflow.com/questions/921262/…
Robin Green

Risposte:


110

Ecco un po 'di codice testato utilizzando la classe URL di Java . Consiglierei di fare un lavoro migliore di me qui per gestire le eccezioni o passarle allo stack di chiamate, però.

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
        }
    }
}

16
DataInputStream.readLine () è deprecato, ma a parte questo ottimo esempio. Ho usato un InputStreamReader () avvolto in un BufferedReader () per ottenere la funzione readLine ().
mjh2007

2
Questo non tiene conto della codifica dei caratteri, quindi anche se sembrerà funzionare per il testo ASCII, alla fine risulterà in "caratteri strani" in caso di mancata corrispondenza.
artbristol

Nella terza riga sostituire DataInputStreamcon BufferedReader. E sostituire "dis = new DataInputStream(new BufferedInputStream(is));"a"dis = new BufferedReader(new InputStreamReader(is));"
kolobok

1
@akapelko Grazie. Ho aggiornato la mia risposta per rimuovere le chiamate a metodi deprecati.
Bill the Lizard

2
che ne dici di chiudere il InputStreamReader?
Alexander - Ripristina Monica

170

Userei un parser HTML decente come Jsoup . Allora è facile come:

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

Gestisce GZIP e risposte in blocchi e la codifica dei caratteri in modo completamente trasparente. Offre anche più vantaggi, come l' attraversamento dell'HTML e la manipolazione da parte dei selettori CSS come può fare jQuery. Devi solo prenderlo come Document, non come file String.

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

Davvero non si desidera eseguire metodi stringa di base o anche un'espressione regolare sui HTML per elaborarlo.

Guarda anche:


3
Buona risposta. Un po 'in ritardo. ;)
jjnguy

59
Meglio che mai.
BalusC

Libreria fantastica :) Grazie per questo.
Jakub P.

Perché nessuno mi ha mai parlato di .html () prima. Ho esaminato così bene come memorizzare facilmente l'html recuperato da Jsoup e questo aiuta molto.
Avamander

per i nuovi arrivati, se si utilizza questa libreria in Android è necessario utilizzarla in thread diversi perché viene eseguita per impostazione predefinita sullo stesso thread dell'applicazione che causerà il lancio dell'applicazioneNetworkOnMainThreadException
Mohammed Elrashied

25

La risposta di Bill è molto buona, ma potresti voler fare alcune cose con la richiesta come la compressione o gli user-agent. Il codice seguente mostra come puoi vari tipi di compressione per le tue richieste.

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();
}

Per impostare anche lo user-agent aggiungere il seguente codice:

conn.setRequestProperty ( "User-agent", "my agent name");

Per coloro che cercano di convertire InputStream in stringa, vedere questa risposta .
SSight 3

setFollowRedirects aiuta, io uso setInstanceFollowRedirects nel mio caso, in molti casi stavo ottenendo pagine web vuote prima di usarlo. Presumo che tu provi a utilizzare la compressione per scaricare il file più velocemente.
gouessej

12

Bene, potresti andare con le librerie integrate come URL e URLConnection , ma non danno molto controllo.

Personalmente andrei con la libreria Apache HTTPClient .
Modifica: HTTPClient è stato impostato per la fine del ciclo di vita da Apache. La sostituzione è: HTTP Components


Non esiste una versione java di System.Net.WebRequest?
FlySwat

1
Più o meno, sarebbe URL. :-) Ad esempio: nuovo URL (" google.com"). OpenStream () // => InputStream
Daniel Spiewak

1
@ Jonathan: quello che ha detto Daniel, per la maggior parte, sebbene WebRequest ti dia più controllo dell'URL. HTTPClient è più vicino in termini di funzionalità, IMO.
Jon Skeet,

9

Tutti gli approcci sopra menzionati non scaricano il testo della pagina web come appare nel browser. in questi giorni molti dati vengono caricati nei browser tramite script in pagine html. nessuna delle tecniche sopra menzionate supporta gli script, scarica solo il testo html. HTMLUNIT supporta i javascript. quindi se stai cercando di scaricare il testo della pagina web come appare nel browser, allora dovresti usare HTMLUNIT .


1

Molto probabilmente dovrai estrarre il codice da una pagina web sicura (protocollo https). Nell'esempio seguente, il file html viene salvato in c: \ temp \ filename.html Buon divertimento!

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();
    }
}

0

Su una macchina Unix / Linux potresti semplicemente eseguire 'wget' ma questa non è davvero un'opzione se stai scrivendo un client multipiattaforma. Ovviamente questo presuppone che tu non voglia fare molto con i dati che scarichi tra il momento in cui li scarichi e quelli che colpiscono il disco.


Vorrei anche iniziare con questo approccio e rifattorizzarlo in un secondo momento se insufficiente
Dustin Getz

0

Jetty ha un client HTTP che può essere utilizzato per scaricare una pagina web.

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();
            }
        }
    }
}

L'esempio stampa il contenuto di una semplice pagina web.

In un tutorial Lettura di una pagina Web in Java ho scritto sei esempi di download di una pagina Web in modo programmatico in Java utilizzando URL, JSoup, HtmlCleaner, Apache HttpClient, Jetty HttpClient e HtmlUnit.


0

Ottieni aiuto da questa classe, ottieni il codice e filtra alcune informazioni.

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;
        }
    }
}

0

Per farlo utilizzando il potente Files.copy di NIO.2 (InputStream in, Path target):

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

-1

Ho usato la risposta effettiva a questo post ( url ) e ho scritto l'output in un file.

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) {

        }

    }
}
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.