Comment télécharger par programme une page Web en Java

117

Je voudrais pouvoir récupérer le code HTML d'une page Web et l'enregistrer dans un Stringfichier, afin que je puisse y faire un traitement. Aussi, comment pourrais-je gérer différents types de compression.

Comment procéderais-je en utilisant Java?

jjnguy
la source
Il s'agit essentiellement d'un cas particulier de stackoverflow.com/questions/921262/…
Robin Green

Réponses:

110

Voici un code testé utilisant la classe URL de Java . Je recommanderais cependant de faire un meilleur travail que je ne le fais ici pour gérer les exceptions ou les transmettre dans la pile d'appels.

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 le lézard
la source
16
DataInputStream.readLine () est obsolète, mais à part ce très bon exemple. J'ai utilisé un InputStreamReader () enveloppé dans un BufferedReader () pour obtenir la fonction readLine ().
mjh2007
2
Cela ne prend pas en compte le codage des caractères, donc bien que cela semble fonctionner pour le texte ASCII, il en résultera finalement des `` caractères étranges '' en cas de non-correspondance.
artbristol
Dans la 3e ligne, remplacez DataInputStreampar BufferedReader. Et remplacer "dis = new DataInputStream(new BufferedInputStream(is));"à"dis = new BufferedReader(new InputStreamReader(is));"
kolobok
1
@akapelko Merci. J'ai mis à jour ma réponse pour supprimer les appels aux méthodes obsolètes.
Bill the Lizard
2
qu'en est-il de fermer le InputStreamReader?
Alexander - Réintégrer Monica
170

J'utiliserais un analyseur HTML décent comme Jsoup . C'est alors aussi simple que:

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

Il gère GZIP et les réponses fragmentées et le codage des caractères de manière totalement transparente. Il offre également plus d'avantages, comme la traversée HTML et la manipulation par des sélecteurs CSS, comme jQuery peut le faire. Vous n'avez qu'à le saisir en tant que Document, pas en tant que String.

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

Vous ne voulez vraiment pas exécuter des méthodes String de base ou même des expressions régulières sur HTML pour le traiter.

Voir également:

BalusC
la source
3
Bonne réponse. Un peu tard. ;)
jjnguy
59
Mieux que jamais.
BalusC
Fantastique bibliothèque :) Merci pour ça.
Jakub P.
Pourquoi personne ne m'a parlé de .html () auparavant. J'ai tellement cherché comment stocker facilement le code HTML récupéré par Jsoup et cela aide beaucoup.
Avamander le
pour les nouveaux arrivants, si vous utilisez cette bibliothèque sous Android, vous devez l'utiliser dans un thread différent car il s'exécute par défaut sur le même thread d'application, ce qui provoquera le lancement de l'applicationNetworkOnMainThreadException
Mohammed Elrashied
25

La réponse de Bill est très bonne, mais vous voudrez peut-être faire certaines choses avec la demande comme la compression ou les agents utilisateurs. Le code suivant montre comment vous pouvez différents types de compression pour vos demandes.

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

Pour définir également l'agent utilisateur, ajoutez le code suivant:

conn.setRequestProperty ( "User-agent", "my agent name");
jjnguy
la source
Pour ceux qui cherchent à convertir InputStream en chaîne, consultez cette réponse .
SSight3
setFollowRedirects aide, j'utilise setInstanceFollowRedirects dans mon cas, je recevais des pages Web vides dans de nombreux cas avant de l'utiliser. Je suppose que vous essayez d'utiliser la compression pour télécharger le fichier plus rapidement.
gouessej
12

Eh bien, vous pouvez utiliser les bibliothèques intégrées telles que URL et URLConnection , mais elles ne donnent pas beaucoup de contrôle.

Personnellement, j'irais avec la bibliothèque Apache HTTPClient .
Edit: HTTPClient a été mis en fin de vie par Apache. Le remplacement est: Composants HTTP

Jon Skeet
la source
Il n'y a pas de version java de System.Net.WebRequest?
FlySwat
1
En quelque sorte, ce serait une URL. :-) Par exemple: nouvelle URL (" google.com"). OpenStream () // => InputStream
Daniel Spiewak
1
@Jonathan: Ce que Daniel a dit, pour la plupart - bien que WebRequest vous donne plus de contrôle que l'URL. HTTPClient est plus proche de la fonctionnalité, IMO.
Jon Skeet
9

Toutes les approches mentionnées ci-dessus ne téléchargent pas le texte de la page Web tel qu'il apparaît dans le navigateur. ces jours-ci, beaucoup de données sont chargées dans les navigateurs via des scripts dans des pages html. aucune des techniques mentionnées ci-dessus ne prend en charge les scripts, ils téléchargent uniquement le texte html. HTMLUNIT prend en charge les javascripts. donc si vous cherchez à télécharger le texte de la page Web tel qu'il apparaît dans le navigateur, vous devez utiliser HTMLUNIT .

user3690910
la source
1

Vous devrez probablement extraire du code d'une page Web sécurisée (protocole https). Dans l'exemple suivant, le fichier html est en cours d'enregistrement dans c: \ temp \ filename.html Enjoy!

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();
    }
}
Spécialiste QA
la source
0

Sur une machine Unix / Linux, vous pouvez simplement lancer 'wget' mais ce n'est pas vraiment une option si vous écrivez un client multiplateforme. Bien sûr, cela suppose que vous ne voulez pas vraiment faire grand-chose avec les données que vous téléchargez entre le moment de leur téléchargement et leur arrivée sur le disque.

Timo Geusch
la source
Je commencerais également par cette approche et la refactoriserais plus tard si elle ne suffisait pas
Dustin Getz
0

Jetty a un client HTTP qui peut être utilisé pour télécharger une page 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'exemple imprime le contenu d'une simple page Web.

Dans un didacticiel de lecture d'une page Web en Java, j'ai écrit six exemples de téléchargement d'une page Web par programmation en Java à l'aide d'URL, JSoup, HtmlCleaner, Apache HttpClient, Jetty HttpClient et HtmlUnit.

Jan Bodnar
la source
0

Obtenez de l'aide de cette classe pour obtenir du code et filtrer certaines informations.

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
la source
0

Pour ce faire en utilisant NIO.2 puissant Files.copy (InputStream in, Path target):

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

J'ai utilisé la réponse réelle à ce message ( url ) et j'ai écrit la sortie dans un fichier.

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
la source