คุณจะดาวน์โหลดเว็บเพจใน Java โดยทางโปรแกรมได้อย่างไร


117

ฉันต้องการที่จะดึง html ของหน้าเว็บและบันทึกลงใน a Stringเพื่อให้ฉันสามารถดำเนินการกับมันได้ นอกจากนี้ฉันจะจัดการการบีบอัดประเภทต่างๆได้อย่างไร

ฉันจะทำอย่างไรโดยใช้ Java


นี่เป็นกรณีพิเศษของstackoverflow.com/questions/921262/…
Robin Green

คำตอบ:


110

นี่คือโค้ดที่ทดสอบโดยใช้คลาสURLของ Java ฉันขอแนะนำให้ทำงานที่ดีกว่าที่ฉันทำที่นี่ในการจัดการข้อยกเว้นหรือส่งผ่านกลุ่มการโทร

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 () เลิกใช้งานแล้ว แต่นอกเหนือจากตัวอย่างที่ดีมาก ฉันใช้ InputStreamReader () ที่ห่อด้วย BufferedReader () เพื่อรับฟังก์ชัน readLine ()
mjh2007

2
สิ่งนี้ไม่ได้คำนึงถึงการเข้ารหัสอักขระดังนั้นแม้ว่าจะดูเหมือนว่าจะใช้งานได้กับข้อความ ASCII แต่ในที่สุดก็จะส่งผลให้ 'อักขระแปลก ๆ ' เมื่อมีความไม่ตรงกัน
artbristol

ในบรรทัดที่ 3 เปลี่ยนไปDataInputStream BufferedReaderและแทนที่"dis = new DataInputStream(new BufferedInputStream(is));"เป็น"dis = new BufferedReader(new InputStreamReader(is));"
kolobok

1
@akapelko ขอบคุณ. ฉันอัปเดตคำตอบเพื่อลบการโทรไปยังเมธอดที่เลิกใช้แล้ว
Bill the Lizard

2
แล้วการปิดInputStreamReaderล่ะ?
อเล็กซานเดอร์ - คืนสถานะโมนิกา

170

ฉันต้องการใช้ตัวแยกวิเคราะห์ HTML ที่ดีเช่นJsoup มันง่ายเหมือน:

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

จัดการ GZIP และการตอบสนองแบบเป็นกลุ่มและการเข้ารหัสอักขระอย่างโปร่งใส มีข้อดีมากกว่าเช่นกันเช่น HTMLข้ามและการจัดการโดยตัวเลือก CSS เช่นเดียวกับที่ jQuery สามารถทำได้ คุณจะต้องคว้ามันให้Documentได้ไม่ใช่เป็นไฟล์String.

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

คุณไม่ต้องการเรียกใช้เมธอด String พื้นฐานหรือแม้แต่ regex บน HTML เพื่อประมวลผล

ดูสิ่งนี้ด้วย:


3
คำตอบที่ดี. สายไปหน่อย. ;)
jjnguy

59
ดีกว่าไม่เคย
BalusC

ห้องสมุดที่ยอดเยี่ยม :) ขอบคุณสำหรับสิ่งนั้น
Jakub P.

ทำไมไม่มีใครบอกฉันเกี่ยวกับ. html () มาก่อน ฉันดูยากมากในการจัดเก็บ html ที่ Jsoup ดึงมาอย่างง่ายดายและนั่นช่วยได้มาก
Avamander

สำหรับผู้มาใหม่หากคุณใช้ไลบรารีนี้ใน Android คุณต้องใช้สิ่งนี้ในเธรดที่แตกต่างกันเพราะมันทำงานโดยค่าเริ่มต้นในเธรดแอปพลิเคชันเดียวกันซึ่งจะทำให้แอปพลิเคชันโยนNetworkOnMainThreadException
Mohammed Elrashied

25

คำตอบของ Bill นั้นดีมาก แต่คุณอาจต้องการทำบางอย่างกับคำขอเช่นการบีบอัดหรือตัวแทนผู้ใช้ รหัสต่อไปนี้แสดงวิธีการบีบอัดประเภทต่างๆตามคำขอของคุณ

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

หากต้องการตั้งค่าตัวแทนผู้ใช้ให้เพิ่มรหัสต่อไปนี้:

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

สำหรับผู้ที่ต้องการแปลง InputStream เป็นสตริงโปรดดูคำตอบนี้
SSight3

setFollowRedirects ช่วยด้วยฉันใช้ setInstanceFollowRedirects ในกรณีของฉันฉันได้รับหน้าเว็บว่างเปล่าในหลาย ๆ กรณีก่อนที่จะใช้สิ่งนั้น ฉันคิดว่าคุณพยายามใช้การบีบอัดเพื่อดาวน์โหลดไฟล์ได้เร็วขึ้น
gouessej

12

คุณสามารถใช้ไลบรารีในตัวเช่นURLและURLConnectionแต่ไม่ได้ให้การควบคุมมากนัก

โดยส่วนตัวแล้วฉันจะใช้ไลบรารีApache HTTPClient
แก้ไข: HTTPClient ถูกกำหนดให้สิ้นสุดอายุการใช้งานโดย Apache สิ่งทดแทนคือ: ส่วนประกอบ HTTP


ไม่มี System.Net.WebRequest เวอร์ชัน java?
FlySwat

1
จัดเรียงนั่นจะเป็น URL :-) ตัวอย่าง: URL ใหม่ (" google.com"). openStream () // => InputStream
Daniel Spiewak

1
@ โจนาธาน: สิ่งที่แดเนียลพูดส่วนใหญ่ - แม้ว่า WebRequest จะให้คุณควบคุมได้มากกว่า URL HTTPClient ใกล้เคียงกับการทำงานมากกว่า IMO
Jon Skeet

9

วิธีการทั้งหมดที่กล่าวมาข้างต้นไม่ดาวน์โหลดข้อความหน้าเว็บตามที่ปรากฏในเบราว์เซอร์ ทุกวันนี้ข้อมูลจำนวนมากถูกโหลดลงในเบราว์เซอร์ผ่านสคริปต์ในหน้า html เทคนิคที่กล่าวถึงข้างต้นไม่รองรับสคริปต์เพียงแค่ดาวน์โหลดข้อความ html เท่านั้น HTMLUNIT รองรับ javascripts ดังนั้นหากคุณกำลังมองหาดาวน์โหลดข้อความหน้าเว็บเป็นลักษณะในเบราว์เซอร์แล้วคุณควรใช้HtmlUnit


1

คุณมักจะต้องดึงรหัสจากหน้าเว็บที่ปลอดภัย (โปรโตคอล https) ในตัวอย่างต่อไปนี้ไฟล์ html จะถูกบันทึกลงใน 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();
    }
}

0

ในกล่อง Unix / Linux คุณสามารถเรียกใช้ 'wget' ได้ แต่นี่ไม่ใช่ตัวเลือกหากคุณกำลังเขียนไคลเอนต์ข้ามแพลตฟอร์ม แน่นอนว่าสิ่งนี้ถือว่าคุณไม่ต้องการทำอะไรมากกับข้อมูลที่คุณดาวน์โหลดระหว่างจุดที่ดาวน์โหลดและไปที่ดิสก์


ฉันจะเริ่มต้นด้วยวิธีนี้และปรับโครงสร้างใหม่ในภายหลังหากไม่เพียงพอ
Dustin Getz

0

Jetty มีไคลเอนต์ HTTP ซึ่งสามารถใช้เพื่อดาวน์โหลดหน้าเว็บ

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

ตัวอย่างจะพิมพ์เนื้อหาของหน้าเว็บธรรมดา

ในบทช่วยสอนการอ่านเว็บเพจใน Javaฉันได้เขียนหกตัวอย่างของการดาวน์โหลดโปรแกรมหน้าเว็บใน Java โดยใช้ URL, JSoup, HtmlCleaner, Apache HttpClient, Jetty HttpClient และ HtmlUnit


0

รับความช่วยเหลือจากคลาสนี้โดยรับโค้ดและกรองข้อมูลบางอย่าง

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

ทำได้โดยใช้ NIO.2 Files.copy ที่มีประสิทธิภาพ (InputStream in, Path target):

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

-1

ฉันใช้คำตอบจริงสำหรับโพสต์นี้ ( url ) และเขียนผลลัพธ์ลงในไฟล์

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

        }

    }
}
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.