Làm cách nào để bạn Tải xuống trang web bằng Java một cách có lập trình


116

Tôi muốn có thể tìm nạp html của một trang web và lưu nó vào a String, để tôi có thể thực hiện một số xử lý trên đó. Ngoài ra, làm thế nào tôi có thể xử lý các loại nén khác nhau.

Tôi sẽ làm điều đó bằng Java như thế nào?


Về cơ bản, đây là một trường hợp đặc biệt của stackoverflow.com/questions/921262/…
Robin Green,

Câu trả lời:


110

Đây là một số mã đã thử nghiệm sử dụng lớp URL của Java . Tuy nhiên, tôi khuyên bạn nên làm công việc tốt hơn là xử lý các ngoại lệ hoặc chuyển chúng lên ngăn xếp cuộc gọi.

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 () không được dùng nữa, nhưng khác với ví dụ rất hay đó. Tôi đã sử dụng InputStreamReader () được bọc trong BufferedReader () để lấy hàm readLine ().
mjh2007

2
Điều này không tính đến mã hóa ký tự, vì vậy mặc dù nó có vẻ hoạt động với văn bản ASCII, nhưng cuối cùng nó sẽ dẫn đến 'các ký tự lạ' khi có sự không khớp.
artbristol

Ở dòng thứ 3 thay thế DataInputStreamthành BufferedReader. Và thay thế "dis = new DataInputStream(new BufferedInputStream(is));"thành"dis = new BufferedReader(new InputStreamReader(is));"
kolobok.

1
@akapelko Cảm ơn bạn. Tôi đã cập nhật câu trả lời của mình để xóa các lệnh gọi đến các phương thức không dùng nữa.
Bill the Lizard

2
những gì về đóng cửa InputStreamReader?
Alexander - Phục hồi Monica

170

Tôi muốn sử dụng một trình phân tích cú pháp HTML tốt như Jsoup . Sau đó, nó dễ dàng như:

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

Nó xử lý GZIP và các phản hồi phân đoạn và mã hóa ký tự hoàn toàn minh bạch. Nó cũng cung cấp nhiều lợi thế hơn, như duyệt qua HTML và thao tác bởi các bộ chọn CSS giống như jQuery có thể làm. Bạn chỉ phải lấy nó dưới dạng Document, không phải như một String.

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

Bạn thực sự không muốn chạy các phương thức String cơ bản hoặc thậm chí regex trên HTML để xử lý nó.

Xem thêm:


3
Câu trả lời tốt. Hơi muộn. ;)
jjnguy

59
Tốt hơn là không bao giờ.
BalusC

Thư viện tuyệt vời :) Thx cho điều đó.
Jakub P.

Tại sao không ai nói với tôi về .html () trước đây. Tôi đã xem xét rất kỹ lưỡng về cách dễ dàng lưu trữ html được tìm nạp bởi Jsoup và điều đó giúp ích rất nhiều.
Avamander

cho những người mới, nếu bạn sử dụng thư viện này trong Android bạn cần phải sử dụng này trong chủ đề khác nhau vì nó chạy theo mặc định trên cùng một chủ đề ứng dụng mà sẽ gây ra các ứng dụng để némNetworkOnMainThreadException
Mohammed Elrashied

24

Câu trả lời của Bill rất hay, nhưng bạn có thể muốn thực hiện một số việc với yêu cầu như nén hoặc tác nhân người dùng. Đoạn mã sau đây cho thấy cách bạn có thể thực hiện nhiều kiểu nén khác nhau theo yêu cầu của mình.

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

Để cũng đặt tác nhân người dùng, hãy thêm mã sau:

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

Đối với những người muốn chuyển đổi InputStream thành chuỗi, hãy xem câu trả lời này .
SSight

12

Chà, bạn có thể sử dụng các thư viện tích hợp sẵn như URLURLConnection , nhưng chúng không cung cấp nhiều quyền kiểm soát.

Cá nhân tôi muốn sử dụng thư viện Apache HTTPClient .
Chỉnh sửa: HTTPClient đã được Apache đặt để kết thúc vòng đời . Thay thế là: Thành phần HTTP


Không có phiên bản java của System.Net.WebRequest?
FlySwat

1
Đại loại, đó sẽ là URL. :-) Ví dụ: URL mới (" google.com"). OpenStream () // => InputStream
Daniel Spiewak 26/10/08

1
@Jonathan: Phần lớn những gì Daniel đã nói - mặc dù WebRequest cung cấp cho bạn nhiều quyền kiểm soát hơn URL. HTTPClient gần hơn về chức năng, IMO.
Jon Skeet

9

Tất cả các cách tiếp cận được đề cập ở trên không tải xuống văn bản trang web như trong trình duyệt. ngày nay, rất nhiều dữ liệu được tải vào các trình duyệt thông qua các tập lệnh trong các trang html. không có kỹ thuật nào được đề cập ở trên hỗ trợ tập lệnh, chúng chỉ tải xuống văn bản html mà thôi. HTMLUNIT hỗ trợ javascrip. vì vậy nếu bạn đang tìm cách tải xuống văn bản trang web giống như trong trình duyệt thì bạn nên sử dụng HTMLUNIT .


1

Rất có thể bạn cần trích xuất mã từ một trang web an toàn (giao thức https). Trong ví dụ sau, tệp html đang được lưu vào c: \ temp \ filename.html Hãy tận hưởng!

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

Trên hộp Unix / Linux, bạn chỉ có thể chạy 'wget' nhưng đây không thực sự là một tùy chọn nếu bạn đang viết một ứng dụng khách đa nền tảng. Tất nhiên, điều này giả định rằng bạn không thực sự muốn làm gì nhiều với dữ liệu bạn tải xuống từ thời điểm tải xuống đến khi nó vào đĩa.


tôi cũng sẽ bắt đầu với cách tiếp cận này và cấu trúc lại nó sau này nếu không đủ
Dustin Getz

0

Jetty có một ứng dụng HTTP có thể được sử dụng để tải xuống một trang 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();
            }
        }
    }
}

Ví dụ in nội dung của một trang web đơn giản.

Trong hướng dẫn Đọc trang web bằng Java, tôi đã viết sáu ví dụ về việc tải xuống một trang web theo chương trình trong Java bằng cách sử dụng URL, JSoup, HtmlCleaner, Apache HttpClient, Jetty HttpClient và HtmlUnit.


0

Nhận trợ giúp từ lớp này, nó lấy mã và lọc một số thông tin.

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

Để làm như vậy bằng cách sử dụng Files.copy mạnh mẽ NIO.2 (InputStream in, Path target):

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

-1

Tôi đã sử dụng câu trả lời thực tế cho bài đăng này ( url ) và ghi đầu ra vào một tệp.

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

        }

    }
}
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.