Bagaimana Anda Mengunduh Halaman Web secara Terprogram di Java

117

Saya ingin dapat mengambil html halaman web dan menyimpannya ke sebuah String, jadi saya dapat melakukan beberapa pemrosesan padanya. Juga, bagaimana saya bisa menangani berbagai jenis kompresi.

Bagaimana saya bisa melakukan itu menggunakan Java?

jjnguy
sumber
Ini pada dasarnya adalah kasus khusus stackoverflow.com/questions/921262/…
Robin Green

Jawaban:

110

Berikut beberapa kode yang diuji menggunakan kelas URL Java . Saya akan merekomendasikan melakukan pekerjaan yang lebih baik daripada yang saya lakukan di sini untuk menangani pengecualian atau meneruskannya ke tumpukan panggilan.

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 the Lizard
sumber
16
DataInputStream.readLine () tidak digunakan lagi, tetapi selain dari contoh yang sangat bagus itu. Saya menggunakan InputStreamReader () yang dibungkus dengan BufferedReader () untuk mendapatkan fungsi readLine ().
mjh2007
2
Ini tidak memperhitungkan pengkodean karakter, jadi meskipun tampaknya berfungsi untuk teks ASCII, pada akhirnya akan menghasilkan 'karakter aneh' saat ada ketidakcocokan.
artbristol
Di baris ke-3 ganti DataInputStreamke BufferedReader. Dan ganti "dis = new DataInputStream(new BufferedInputStream(is));"ke"dis = new BufferedReader(new InputStreamReader(is));"
kolobok
1
@akapelko Terima kasih. Saya memperbarui jawaban saya untuk menghapus panggilan ke metode yang tidak digunakan lagi.
Bill the Lizard
2
bagaimana dengan menutup InputStreamReader?
Alexander - Kembalikan Monica
170

Saya akan menggunakan parser HTML yang layak seperti Jsoup . Semudah itu:

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

Ini menangani GZIP dan tanggapan terpotong serta pengkodean karakter sepenuhnya secara transparan. Ini juga menawarkan lebih banyak keuntungan, seperti traverse HTML dan manipulasi oleh pemilih CSS seperti yang dapat dilakukan jQuery. Anda hanya perlu mengambilnya sebagai Document, bukan sebagai file String.

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

Anda benar - benar tidak ingin menjalankan metode String dasar atau bahkan regex pada HTML untuk memprosesnya.

Lihat juga:

BalusC
sumber
3
Jawaban yang bagus. Sedikit terlambat. ;)
jjnguy
59
Lebih baik daripada tidak sama sekali.
BalusC
Perpustakaan yang fantastis :) Terima kasih untuk itu.
Jakub P.
Mengapa tidak ada yang memberi tahu saya tentang .html () sebelumnya. Saya melihat begitu keras bagaimana cara mudah menyimpan html yang diambil oleh Jsoup dan itu sangat membantu.
Avamander
untuk pendatang baru, jika Anda menggunakan pustaka ini di android, Anda perlu menggunakannya di utas yang berbeda karena ini berjalan secara default pada utas aplikasi yang sama yang akan menyebabkan aplikasi NetworkOnMainThreadException
terlempar
25

Jawaban Bill sangat bagus, tetapi Anda mungkin ingin melakukan beberapa hal dengan permintaan seperti kompresi atau agen pengguna. Kode berikut menunjukkan bagaimana Anda dapat berbagai jenis kompresi untuk permintaan Anda.

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

Untuk juga mengatur agen pengguna, tambahkan kode berikut:

conn.setRequestProperty ( "User-agent", "my agent name");
jjnguy
sumber
Bagi mereka yang ingin mengonversi InputStream menjadi string, lihat jawaban ini .
SSight3
setFollowRedirects membantu, saya menggunakan setInstanceFollowRedirects dalam kasus saya, saya mendapatkan halaman web kosong dalam banyak kasus sebelum menggunakannya. Saya berasumsi bahwa Anda mencoba menggunakan kompresi untuk mengunduh file lebih cepat.
gouessej
12

Nah, Anda bisa menggunakan pustaka bawaan seperti URL dan URLConnection , tetapi mereka tidak memberikan banyak kendali.

Secara pribadi saya akan menggunakan perpustakaan Apache HTTPClient .
Sunting: HTTPClient telah disetel ke akhir masa pakai oleh Apache. Penggantinya adalah: Komponen HTTP

Jon Skeet
sumber
Tidak ada versi java dari System.Net.WebRequest?
FlySwat
1
Semacam itu, itu akan menjadi URL. :-) Misalnya: URL baru (" google.com"). OpenStream () // => InputStream
Daniel Spiewak
1
@Jonathan: Apa yang Daniel katakan, sebagian besar - meskipun WebRequest memberi Anda lebih banyak kontrol daripada URL. HTTPClient lebih dekat dalam fungsionalitas, IMO.
Jon Skeet
9

Semua pendekatan yang disebutkan di atas tidak mengunduh teks halaman web seperti yang terlihat di browser. hari ini banyak data dimuat ke browser melalui skrip di halaman html. tidak ada teknik yang disebutkan di atas mendukung skrip, mereka hanya mengunduh teks html saja. HTMLUNIT mendukung javascript. jadi jika Anda ingin mengunduh teks halaman web seperti yang terlihat di browser, maka Anda harus menggunakan HTMLUNIT .

pengguna3690910
sumber
1

Anda kemungkinan besar perlu mengekstrak kode dari halaman web yang aman (protokol https). Dalam contoh berikut, file html sedang disimpan ke c: \ temp \ filename.html Selamat menikmati!

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();
    }
}
Spesialis QA
sumber
0

Pada kotak Unix / Linux Anda bisa menjalankan 'wget' tetapi ini sebenarnya bukan pilihan jika Anda menulis klien lintas platform. Tentu saja ini mengasumsikan bahwa Anda tidak benar-benar ingin berbuat banyak dengan data yang Anda unduh antara saat mengunduhnya dan itu mengenai disk.

Timo Geusch
sumber
saya juga akan mulai dengan pendekatan ini dan memfaktorkan ulang nanti jika tidak cukup
Dustin Getz
0

Jetty memiliki klien HTTP yang dapat digunakan untuk mengunduh halaman 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();
            }
        }
    }
}

Contoh mencetak konten halaman web sederhana.

Dalam tutorial Membaca halaman web di Java, saya telah menulis enam contoh dowloading halaman web secara terprogram di Java menggunakan URL, JSoup, HtmlCleaner, Apache HttpClient, Jetty HttpClient, dan HtmlUnit.

Jan Bodnar
sumber
0

Dapatkan bantuan dari kelas ini untuk mendapatkan kode dan memfilter beberapa informasi.

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
sumber
0

Untuk melakukannya menggunakan Files.copy yang kuat NIO.2 (InputStream in, Path target):

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

Saya menggunakan jawaban sebenarnya untuk posting ini ( url ) dan menulis hasilnya ke dalam 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) {

        }

    }
}
A_01
sumber