JWorld@TW the best professional Java site in Taiwan
      註冊 | 登入 | 全文檢索 | 排行榜  

» JWorld@TW » Java 程式分享區 » Web  

按列印兼容模式列印這個話題 列印話題    把這個話題寄給朋友 寄給朋友    訂閱主題
reply to topicthreaded modego to previous topicgo to next topic
本主題所含的標籤
作者 [網路] 自製網頁圖片下載器
robertvmp





發文: 2
積分: 0
於 2010-07-19 13:40 user profilesend a private message to userreply to postreply to postsearch all posts byselect and copy to clipboard. 
ie only, sorry for netscape users:-)add this post to my favorite list
由於嚮往 xlinx 大的 [網路]自製抓DCVIEW攝影 照片 程式 簡單好用 [一按鈕搞定]
http://www.javaworld.com.tw/jute/post/view?bid=35&id=56772&tpg=1&ppg=1&sty=0&age=0#56772

剛下載來時,那時程式還是可以正常使用的,但是我的程度太差,完全看不懂,
最近想說再來研究一番,但程式卻已無法正常執行了,
研究了半天,也不是搞得很清楚,於是自己寫寫看,
順便了解一下基本的原理,
當然無法像 xlinx 大的那樣可以自動登入與下載與識別圖片。
只有簡單的所見即所得的,看的到就抓得到。

由於寫程式的時候遇到很多問題,都是參考網站上的相關經驗。
且受益良多,於是野人獻曝地把自己完成的東西也放上來分享與記錄自己。

使用&功能說明:
1.貼上目標網址,再按下[執行]即可下載。
2.預設會在程式的所在資料夾下再建立一個 pic 的資料夾放置圖片。
3.預設下載 20 KB 以上的圖片,重複的檔案將被複寫。
4.點選Table中每一行的fileName部分,可預覽下載完成的圖片。

PS:
1.本程式僅供 java 技術測試與分享,其餘目的皆與本人無關。
2.本程式僅在DCView上測試過,且這不是相簿下載器。
3.本人作業環境是 Eclipse + JRE System Library [ jdk1.6.0_05 ]

後記:
Duncan 大大到底是何許人也,怎麼什麼問題他都可以回答啊??
真神人也,要怎樣才能像他那樣強呢...

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Container;
import java.awt.Image;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.HttpURLConnection;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLConnection;
 
import javax.swing.Box;
import javax.swing.BoxLayout;
import javax.swing.ImageIcon;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.JTextField;
import javax.swing.border.EmptyBorder;
import javax.swing.event.ListSelectionEvent;
import javax.swing.table.DefaultTableModel;
 
//
public class picBox extends JFrame {
  JTable table = null ;
  JTextField txtURL = null;
  Container cp = null;
  JLabel lbPicPreview = null; 
 
  final int atLeastSizeKB = 20 ;
  final String defaultFolder = "pic/" ;
  
  final double defaultW = 300.0 ;//自訂SizeW:
  final double defaultH = 300.0 ;//自訂SizeH:
  
  public static void main(String args[]) {
    new picBox();
  }
  
  picBox() {
    super("DCView WebPage Image Downloader");
    String testURL1="http://gallery.dcview.com/showGallery.php?id=8831";//For Test 風景
    String testURL2="http://gallery.dcview.com/showGallery.php?id=9309";//For Test 正妹
    //JTextField
    txtURL = new JTextField("");
    txtURL.setText(testURL2);
    
    //JButton: btnExe
    JButton btnExe  = new JButton("執行") ;    
    btnExe.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                try {
                  ActionExe(evt);
        } catch (InterruptedException e) {
          e.printStackTrace();
        }
            }
      });
    
    //JButton: Exit
    JButton btnExit  = new JButton("離開") ;
    btnExit.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
          System.exit(0);
            }
      });
    //Preview Window
    lbPicPreview = new JLabel(changeImage("00.jpg"));
    
    try{
      //Table//以Model物件宣告建立表格的JTable元件
      table = new JTable(){
        public void valueChanged(ListSelectionEvent e){
          super.valueChanged(e); //呼叫基礎類別的valueChanged()方法, 否則選取動作無法正常執行
          if( table.getSelectedRow() == -1) return;//取得表格目前的選取列,若沒有選取列則終止執行方法
        }
      };    
      table.setAutoResizeMode(JTable.AUTO_RESIZE_OFF);         
      table.setSelectionBackground(Color.ORANGE);//設定選取背景顏色    
      table.setCellSelectionEnabled(true); //設定允許儲存格選取
      
      //取得處理表格資料的Model物件,建立關聯
      DefaultTableModel dtm = (DefaultTableModel)table.getModel(); //宣告處理表格資料的TableModel物件
      //Set ColumnHeader Name
      dtm.addColumn( "Item" );
      dtm.addColumn( "FileName" );
      dtm.addColumn( "Size(KB)" );
      
      //欄寬設定
      table.getColumnModel().getColumn(0).setPreferredWidth(40);  //設定欄位的喜好寬度為40
      table.getColumnModel().getColumn(1).setPreferredWidth(270); //設定欄位的喜好寬度為270
      table.getColumnModel().getColumn(2).setPreferredWidth(70);  //設定欄位的喜好寬度為70
      
      //註冊回應JTable元件的MouseEvent事件的監聽器物件
      table.addMouseListener(new MouseAdapter(){
        public void mouseClicked(MouseEvent e){
          int selRow  = table.rowAtPoint(e.getPoint());//取得滑鼠點選位置所在之資料的列索引
          String Size = (String) table.getValueAt(selRow, 2);  //取得被點選資料列的第3欄的值
          if (Integer.parseInt(Size)> 0 ){
            String imgPath = defaultFolder + (String) table.getValueAt(selRow, 1);  //取得被點選資料列的第2欄的值
            lbPicPreview.setIcon((changeImage(imgPath)));
          }
        }
      });
      
    }catch ( Exception  e){
      e.printStackTrace();
    }
    
    //setup main window
    Box bxRow1= new Box(BoxLayout.X_AXIS);
      bxRow1.add(Box.createHorizontalStrut(10));//Strut:固定長度的透明支架
      bxRow1.add(new JLabel("Target URL :"));
      bxRow1.add(Box.createHorizontalStrut(10));//Strut:固定長度的透明支架
      bxRow1.add(txtURL); 
      bxRow1.add(Box.createHorizontalStrut(10));//Strut:固定長度的透明支架
      bxRow1.add(btnExe);
      bxRow1.add(Box.createHorizontalStrut(10));//Strut:固定長度的透明支架
      bxRow1.add(btnExit);
      bxRow1.add(Box.createHorizontalStrut(10));//Strut:固定長度的透明支架 
    
      Box bxMix = new Box(BoxLayout.X_AXIS);
      bxMix.add(Box.createHorizontalStrut(10));//Strut:固定長度的透明支架
      bxMix.add(new JScrollPane(table));//放在 JScrollPane 內才有, Scrollbar
      bxMix.add(Box.createHorizontalStrut(10));//Strut:固定長度的透明支架
      bxMix.add(lbPicPreview);
      bxMix.add(Box.createVerticalStrut(10));//Strut:固定長度的透明支架
 
      //內容面板
    cp = getContentPane(); //取得內容面版
    cp.setLayout(new BorderLayout(10, 10));  //建立各區域水平、垂直間距為10的BorderLayout物件
    
    //將各按鈕控制項,加入版面的指定位置
    cp.add(bxRow1, BorderLayout.NORTH);
    cp.add(bxMix);
    
    ///設定根面版四周將使用寬度為5的空白框線
    getRootPane().setBorder(new EmptyBorder(5, 5, 5, 5));
    
    //設定視窗預設的關閉動作、視窗大小, 並顯示視窗  
    setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    setSize(750, 500);//pack();強迫視窗會變成最佳尺寸, 使 setSize 無效
    setVisible(true);
 
  }
 
  private void ActionExe(java.awt.event.ActionEvent evt) throws InterruptedException{
    this.setTitle("Analyzing and Downloading...");
    //reset Table
    DefaultTableModel dtm = (DefaultTableModel)table.getModel();
    for (int kk = dtm.getRowCount() - 1  ; kk >= 0 ; kk -- ){
      dtm.removeRow(kk); 
    }
    
    String URL = txtURL.getText().trim();
    //讀入網頁原始碼
    if (readPage(URL) == -1){
      addMatch("ReadPage Error !!", 0 );
      return; 
      };
      
    //分析網頁資料
    if (analyPage()== -1){ 
      addMatch("AnalyPage Error !!", 0 );
      return;
      };   
    //這個 ActionExe 的 thread 比 analyPage 的 thead 早結束  
  }
  
  //換照片時,自動縮小
  private ImageIcon  changeImage(String imgPath){
    ImageIcon img = new ImageIcon(imgPath) ;
    double imgW = img.getIconWidth();
    double imgH = img.getIconHeight();
    double scale = 1.0;
    if (imgW >= imgH){
      scale = defaultW / imgW  ;
      img.setImage(img.getImage().getScaledInstance( (int) defaultW, (int) (imgH * scale) ,Image.SCALE_DEFAULT));
    }else{
      scale = defaultH / imgH ;
      img.setImage(img.getImage().getScaledInstance((int)(imgW * scale) , (int)defaultH,Image.SCALE_DEFAULT));
    }    
    return img;
  }
  
  // Add data to table.
  private void addMatch(String path, long size ) throws InterruptedException {
    DefaultTableModel dtm = (DefaultTableModel)table.getModel();
    dtm.addRow(new String[] {String.valueOf(dtm.getRowCount()+1), path, (size>0 ? setComma(size):"")});  
    if (path.indexOf("OK") > -1){this.setTitle("DCView WebPage Image Downloader");}
  }
  
  private String setComma( long size ) {
    int idx = 0;
    String s = String.valueOf(size);
    StringBuffer sb = new StringBuffer("") ;
    for(int k=s.length() ; k>0 ; k-- ){
      idx++;
      sb.append((idx != s.length()&& idx%3==0)? s.substring(k-1, k) + "," : s.substring(k-1, k));
    }
    return sb.reverse().toString();  
  }
 
  //分析網頁
  public  int  analyPage() {
      int c;
      final StringBuffer sb = new StringBuffer(""); 
      try{
        InputStreamReader isr =  new InputStreamReader(new FileInputStream("WebPage.txt"),"Big5");
        while((c = isr.read()) != -1){ //Null, the end of file
          sb.append((char) c);
            }
        //參考:http://www.javaworld.com.tw/jute/post/view?bid=29&id=42796&tpg=1&ppg=1&sty=0&age=0#42796
        //因為用 while 會佔住 cpu , 所以加一個 thead 來執行, 以讓畫面可在每加一筆後,立即更新
        //也就是 把 time-consuming 工作以獨立的 thread 來執行
        new Thread(){
          public void run() {
            String[] target = {".jpg",".bmp",".png"};//pass gif
            for ( int k=0 ; k < target.length ; k++){  
              int idx=0, start = 0 , tgtPos = 0 , httpPos = 0 ;
              StringBuffer sbPage = new StringBuffer(sb.toString().toLowerCase());
              
              while (true){
                tgtPos = sbPage.indexOf(target[k], start);
                if (tgtPos == -1 ){ break; } 
//                if ( (idx++) >= 5 ){ break; }//for test
                
                //get target path
                httpPos = sbPage.lastIndexOf("http", tgtPos);
                String tgtURL = sbPage.substring(httpPos, tgtPos + 4).toString() ;  
                String fileName = tgtURL.substring(tgtURL.lastIndexOf("/")+1) ;
                          
                //檢查一些規則
                if ( checkRule(tgtURL , fileName) ){
                  long fileSize = downloadPic(tgtURL);
                  try {
                   if(fileSize > 0){
                     addMatch(fileName , fileSize );
                     Thread.sleep(10);
                   }
                }catch (InterruptedException e) {
                  e.printStackTrace();
                }  
                }
                //reset
                start = tgtPos + 4 ;
              }              
                }
            
            //Log for done
            try {
            addMatch("OKOK, Download Done !!", 0 );
          } catch (InterruptedException e) {
            e.printStackTrace();
          }
          }
        }.start();
       }catch (IOException e) {
      e.printStackTrace();
      return -1;
    }
       return 1;
    }
  
  //避掉分析錯誤或無法存檔的情況
  public  boolean checkRule( String URL , String fileName ) {
 
    if ( !URL.substring(0, 4).equals("http") ){
      return false; //避掉一些相對路徑的圖片,這通常都很小
    
    }else if ( URL.indexOf('>') > 0 || URL.indexOf('<') > 0  ){
      //一些分析錯誤的情況
      //http://www.facebook.com/pages/DCView/402684696689?v=wall&ref=ts"><img title="facebook" alt="facebook" src="/i/facebook_20.png
      return false; 
    
    }else if (fileName.length() > 170 ){      
    //Windows檔名長度限制260字元,但再加上本身資料夾路徑,D:\eclipse\WorkSpace\picBox\pic 所以就更少了
      return false; 
    }
    
    //check double-file
    for (int k=0; k< table.getRowCount() ; k++){
      String downloadedFile = (String) table.getValueAt(k, 1);
      if ( downloadedFile.equals(fileName) ){//已下載, <img> 內 src= 和 alt= 裡面的圖片是一樣的
        return false; 
      }
    }
    
    return true;
  }
  
  //讀入網頁原始碼
  public  static int readPage( String strURL ) {
      int chunksize = 4096;
      byte[] chunk = new byte[chunksize];
      int count;
      try  {    
        URL pageUrl = new URL(strURL );
     
          // 讀入網頁(位元串流)
          BufferedInputStream bis = new BufferedInputStream(pageUrl.openStream());
          BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream("WebPage.txt", false));
          while ((count = bis.read(chunk, 0, chunksize)) != -1) {
            bos.write(chunk, 0, count); // 寫入檔案
          }
          bos.flush();
          bos.close();
          bis.close();
        
       }catch (IOException e) {
         e.printStackTrace();
         return -1;
       }
       return 1;
    }
  
   
  //下載圖片
  public long  downloadPic(String strURL){
    long fileSize = 0;
    FileOutputStream fos = null ;
    InputStream is = null ;
    try {
      System.out.println("Checking -> " + strURL);
      
      //為了避免 403 的錯誤,http://www.javaworld.com.tw/jute/post/view?bid=38&id=108431&tpg=1&ppg=1&sty=0&age=0#108431
      URL url = new URL(strURL);      
      URLConnection URLConn = (HttpURLConnection) url.openConnection();
      URLConn.setRequestProperty("User-agent","IE/6.0");
      fileSize = ( URLConn.getContentLength() / 1024) + 1 ; //Unit:KB , 自動進位^^
      
      if ( URLConn.getContentLength() > 0 && URLConn.getContentType().indexOf("text/html") >= 0) {        
        //未被授存取的圖片, 無權進入的網頁, 會回應出此類訊息 URLConn.getContentType()=> text/html; charset=iso-8859-1
        //例如 http://upload.dcview.com/u/gallery/201007/8191a51eea9df2e7defa401a36ded0b2.jpg
        return -1;
      }else if ( fileSize <= atLeastSizeKB ){
        //小於 atLeastSizeKB 不下載
        return -1;        
      }
      
      //check Folder for picture
      File f = new File(defaultFolder) ;
      if (!f.exists()){f.mkdirs();}
      f = null;
 
      //
      String filePath = defaultFolder + strURL.substring(strURL.lastIndexOf("/")+1) ;
      fos = new FileOutputStream(filePath, false);
      is = URLConn.getInputStream(); // OldScript:url.openStream();
      
      //==讀到 buffer[] 因為不能保證連線的品質,或是檔案較大的時候,也許會有lose
      int chunkSize = 1024 * 8;
      byte[] buf = new byte[chunkSize];
      int readLen;
      System.out.println("Downloading -> " + strURL);
      while ((readLen = is.read( buf, 0, buf.length)) != -1) {
         fos.write(buf, 0, readLen);
      }                  
      is.close();      fos.close();
      
      //顯示已下載的圖片
        lbPicPreview.setIcon((changeImage(filePath)));
        lbPicPreview.repaint();
      
    } catch (MalformedURLException e) {
      fileSize = -1;
      e.printStackTrace();
    } catch (FileNotFoundException e) {
      fileSize = -1;
      e.printStackTrace();
    } catch (IOException e) {
      fileSize = -1;
      e.printStackTrace();
    } catch (Throwable e) {
      fileSize = -1;
      e.getMessage();
      e.printStackTrace();
    }finally{
      try {
        if (is !=null ){is.close();}
        if (fos !=null ){fos.close();}
      } catch (IOException e) {
        e.printStackTrace();
      }
    }
      
    return fileSize ;
  }
}
 


picBox.zip (34.71k)


robertvmp edited on 2010-07-19 15:06
reply to postreply to post
作者 Re:[網路] 自製網頁圖片下載器 [Re:robertvmp]
robertvmp





發文: 2
積分: 0
於 2010-07-20 13:37 user profilesend a private message to userreply to postreply to postsearch all posts byselect and copy to clipboard. 
ie only, sorry for netscape users:-)add this post to my favorite list
補上一張 [執行] 完成後的圖片..



reply to postreply to post
作者 Re:[網路] 自製網頁圖片下載器 [Re:robertvmp]
小a





發文: 68
積分: 0
於 2010-11-21 14:56 user profilesend a private message to userreply to postreply to postsearch all posts byselect and copy to clipboard. 
ie only, sorry for netscape users:-)add this post to my favorite list
robertvmp wrote:
補上一張 [執行] 完成後的圖片..




你測試奇摩網站試試看, 有bug


reply to postreply to post
» JWorld@TW »  Java 程式分享區 » Web

reply to topicthreaded modego to previous topicgo to next topic
  已讀文章
  新的文章
  被刪除的文章
Jump to the top of page

JWorld@TW 本站商標資訊

Powered by Powerful JuteForum® Version Jute 1.5.8