6

URLConnectionを介してWebページ全体を取得しようとしています。

これを行うための最も効率的な方法は何ですか?

私はすでにこれを行っています:

URL url = new URL("http://www.google.com/");
URLConnection connection;
connection = url.openConnection();
InputStream in = connection.getInputStream();        
BufferedReader bf = new BufferedReader(new InputStreamReader(in));
StringBuffer html = new StringBuffer();
String line = bf.readLine();
while(line!=null){
    html.append(line);
    line = bf.readLine();
}
bf.close();

htmlにはHTMLページ全体が含まれます。

4

5 に答える 5

8

これが最善の方法だと思います。ページのサイズは固定されているため(「それが何であるか」)、メモリを改善することはできません。内容を入手したら圧縮できるかもしれませんが、その形式ではあまり役に立ちません。最終的には、HTMLをDOMツリーに解析したいと思うでしょう。

読み取りを並列化するために行うことは、ソリューションを過度に複雑にします。

デフォルトサイズが2048または4096のStringBuilderを使用することをお勧めします。

投稿したコードが不十分だと思うのはなぜですか?あなたは時期尚早の最適化の罪を犯しているように聞こえます。

あなたが持っているもので走り、夜寝なさい。

于 2010-10-12T20:32:06.127 に答える
3

取得したHTMLで何をしたいですか?解析しますか?少しまともな HTML パーサーには、直接URLorを取るコンストラクターまたはメソッド引数が既にあるInputStreamので、そのようなストリーミング パフォーマンスについて心配する必要がないことを知っておくとよいでしょう。

やりたいことがすべて前の質問に記載されていると仮定すると、たとえばJsoupを使用すると、次のように非常に簡単にこれらすべてのニュース リンクを取得できます。

Document document = Jsoup.connect("http://news.google.com.ar/nwshp?hl=es&tab=wn").get();
Elements newsLinks = document.select("h2.title a:eq(0)");
for (Element newsLink : newsLinks) {
    System.out.println(newsLink.attr("href"));
}

これにより、わずか数秒後に次の結果が得られます。

http://www.infobae.com/mundo/541259-100970-0-Pinera-confirmo-que-el-rescate-comenzara-las-20-y-durara-24-y-48-horas
http://www.lagaceta.com.ar/nota/403112/Argentina/Boudou-disculpo-con-DAIA-pero-volvio-cuestionar-medios.html
http://www.abc.es/agencias/noticia.asp?noticia=550415
http://www.google.com/hostednews/epa/article/ALeqM5i6x9rhP150KfqGJvwh56O-thi4VA?docId=1383133
http://www.abc.es/agencias/noticia.asp?noticia=550292
http://www.univision.com/contentroot/wirefeeds/noticias/8307387.shtml
http://noticias.terra.com.ar/internacionales/ecuador-apoya-reclamo-argentino-por-ejercicios-en-malvinas,3361af2a712ab210VgnVCM4000009bf154d0RCRD.html
http://www.infocielo.com/IC/Home/index.php?ver_nota=22642
http://www.larazon.com.ar/economia/Cristina-Fernandez-Censo-indispensable-pais_0_176100098.html
http://www.infobae.com/finanzas/541254-101275-0-Energeticas-llevaron-la-Bolsa-portena-ganancias
http://www.telam.com.ar/vernota.php?tipo=N&idPub=200661&id=381154&dis=1&sec=1
http://www.ambito.com/noticia.asp?id=547722
http://www.canal-ar.com.ar/noticias/noticiamuestra.asp?Id=9469
http://www.pagina12.com.ar/diario/cdigital/31-154760-2010-10-12.html
http://www.lanacion.com.ar/nota.asp?nota_id=1314014
http://www.rpp.com.pe/2010-10-12-ganador-del-pulitzer-destaca-nobel-de-mvll-noticia_302221.html
http://www.lanueva.com/hoy/nota/b44a7553a7/1/79481.html
http://www.larazon.com.ar/show/sdf_0_176100096.html
http://www.losandes.com.ar/notas/2010/10/12/batista-siento-comodo-dieron-respaldo-520595.asp
http://deportes.terra.com.ar/futbol/los-rumores-empiezan-a-complicar-la-vida-de-river-y-vuelve-a-sonar-gallego,a24483b8702ab210VgnVCM20000099f154d0RCRD.html
http://www.clarin.com/deportes/futbol/Exigieron-Roman-regreso-Huracan_0_352164993.html
http://www.el-litoral.com.ar/leer_noticia.asp?idnoticia=146622
http://www.nuevodiarioweb.com.ar/nota/181453/Locales/C%C3%A1ncer_mama:_200_casos_a%C3%B1o_Santiago.html
http://www.ultimahora.com/notas/367322-Funcionarios-sanitarios-capacitaran-sobre-cancer-de-mama
http://www.lanueva.com/hoy/nota/65092f2044/1/79477.html
http://www.infobae.com/policiales/541220-101275-0-Se-suspendio-la-declaracion-del-marido-Fernanda-Lemos
http://www.clarin.com/sociedad/educacion/titulo_0_352164863.html

正規表現は HTML を解析するための絶対に間違ったツールであると誰かがすでに言っていましたか? ;)

以下も参照してください。

于 2010-10-12T21:14:25.580 に答える
2

Apache から commons-io を使用してみることができます (http://commons.apache.org/io/api-release/org/apache/commons/io/IOUtils.html)。

new String(IOUtils.toCharArray(connection.getInputStream()))
于 2010-10-12T20:38:16.027 に答える
2

あなたのアプローチはかなり良さそうに見えますが、行ごとに中間の String オブジェクトを作成しないようにすることで、より効率的にすることができます。

これを行う方法は、一時的な char[] バッファに直接読み込むことです。

これを行うコードを少し変更したバージョンを次に示します (わかりやすくするために、すべてのエラー チェック、例外処理などを除いています)。

        URL url = new URL("http://www.google.com/");
        URLConnection connection;
        connection = url.openConnection();
        InputStream in = connection.getInputStream();        
        BufferedReader bf = new BufferedReader(new InputStreamReader(in));
        StringBuffer html = new StringBuffer();

        char[] charBuffer = new char[4096];
        int count=0;

        do {
            count=bf.read(charBuffer, 0, 4096);
            if (count>=0) html.append(charBuffer,0,count);
        } while (count>0);
        bf.close();

さらにパフォーマンスを向上させるために、このコードが頻繁に呼び出される場合は、文字配列と StringBuffer を事前に割り当てるなど、少し余分なことを行うことができます。

于 2010-10-12T20:45:23.477 に答える
1

いくつかの技術的な考慮事項があります。URLConnection の代わりに HTTPURLConnection を使用したい場合があります。

HTTPURLConnection はチャンク転送エンコーディングをサポートしています。これにより、作業を開始する前にすべてのコンテンツをバッファリングするのではなく、チャンクでデータを処理できます。これにより、ユーザー エクスペリエンスが向上します。

また、HTTPURLConnection は永続的な接続をサポートしています。すぐに別のリソースをリクエストするつもりなら、なぜその接続を閉じるのでしょうか? Web サーバーとの TCP 接続を開いたままにしておくと、リソースごとに新しい TCP 接続を確立するオーバーヘッド (レイテンシー) を費やすことなく、アプリケーションで複数のリソースをすばやくダウンロードできます。

サーバーに gzip をサポートしていることを伝え、コンテンツが圧縮されていることが応答ヘッダーに示されている場合は、GZIPInputStream を BufferedReader でラップします。

于 2010-10-12T21:34:08.607 に答える