多线程实现百度图片爬虫

由于百度图片采用异步加载的方式,因此不能通过静态标签<img src>匹配找到图片的url,可考虑通过向服务器发送ajax请求的方式下载图片。

打开360浏览器或Chrom,按F12,切换到Network标签,然后将网页向下拉,观察发现地址栏的网址并没有发生变化,而图片在增加。

 

可以发现在下拉过程中会不断出现avatarjson请求,点开请求头信息,分析两个请求URL:

http://image.baidu.com/search/avatarjson?tn=resultjsonavatarnew&ie=utf-8&word=%E5%AE%8B%E4%BD%B3&cg=star&pn=90&rn=30&itg=0&z=0&fr=&width=&height=&lm=-1&ic=0&s=0&st=-1&gsm=5a

http://image.baidu.com/search/avatarjson?tn=resultjsonavatarnew&ie=utf-8&word=%E5%AE%8B%E4%BD%B3&cg=star&pn=120&rn=30&itg=0&z=0&fr=&width=&height=&lm=-1&ic=0&s=0&st=-1&gsm=78

变化的地方如下:

word:搜索关键字,要用URL Encode,即非字母字符被替换成%后加两位十六进制数;

pn:每次递增30,每次异步请求可加载30张图片;

gsm: pn的十六进制值;

因此每次请求我们只需改变pn及gsm的值即可,用page对请求页面计数,初次请求时page为0,以后每次请求page加1。

 

将keyword进行URL Encode编码后,可以拼接出page次请求的URL:

http://image.baidu.com/search/avatarjson?tn=resultjsonavatarnew&ie=utf-8&word="+keyword+"&cg=star&pn="+page*30+"&rn=30&itg=0&z=0&fr=&width=&height=&lm=-1&ic=0&s=0&st=-1&gsm="+Integer.toHexString(page*30)

请求返回JSON数据,点击preview标签,找到imgs

 

发现一张图片有4种URL:fromURL,middleURL,thumbURL,objURL,前三种有反爬措施,因此采用objURL.

 

因此得到图片爬取的流程: 

1)将搜索关键字keyword编码后得到请求地址;

2)得到该请求地址的JSON数据;

3)分析JSON数据匹配出objURL地址;

4)请求此地址下载图片。

 

多线程实现

  为了加快爬取的速度,采用多线程设计。  各个线程同时下载各自请求得到的图片,因此要确保每个线程每次请求时的page不同,因此为page操作要实现同步。

程序如下:

 

[java] view plain copy
 
 在CODE上查看代码片派生到我的代码片
  1. import java.util.List;  
  2. import java.util.concurrent.locks.Lock;  
  3. import java.util.concurrent.locks.ReentrantLock;  
  4. import java.util.regex.Matcher;  
  5. import java.util.regex.Pattern;  
  6. import java.io.File;  
  7. import java.io.FileNotFoundException;  
  8. import java.io.FileOutputStream;  
  9. import java.io.IOException;  
  10. import java.io.InputStream;  
  11. import java.io.UnsupportedEncodingException;  
  12. import java.net.HttpURLConnection;  
  13. import java.net.URL;  
  14. import java.net.URLConnection;  
  15. import java.net.URLEncoder;  
  16. import java.util.ArrayList;  
  17.   
  18. /** 
  19.  * @author Administrator 
  20.  * 爬取百度图片,百度图片加载方式:异步加载,瀑布流式 
  21.  */  
  22. public class Crawer  
  23. {  
  24.     private static int page=-1;   
  25.     private static final String ENCODE="UTF-8";//编码  
  26.     private static Lock lock=new ReentrantLock();  
  27.     /** 
  28.      * 将中文转换成URL编码 
  29.      * @param keyword     
  30.      */  
  31.     public static String  encode(String keyword) throws UnsupportedEncodingException   
  32.     {  
  33.         return new String(URLEncoder.encode(keyword,ENCODE).getBytes());  
  34.     }  
  35.       
  36.     public static void main(String[] args) throws UnsupportedEncodingException   
  37.     {  
  38.         String name="孙艺珍";  
  39.         String downloadPath="F:\\downloadPic\\"+name+"\\";  
  40.         String keyword=encode(name);  
  41.         for(int i=0;i<8;i++)  
  42.         {  
  43.             new Thread("Thread--"+i){  
  44.                 public void run()  
  45.                 {  
  46.                     downloadPic(keyword,downloadPath);  
  47.                 }  
  48.                   
  49.             }.start();  
  50.         }         
  51.     }  
  52.     public static void downloadPic(String keyword,String downloadPath)  
  53.     {      
  54.         File path=new File(downloadPath);  
  55.         if(!path.exists())  
  56.             path.mkdirs();  
  57.         while(!Thread.interrupted())  
  58.         {  
  59.            lock.lock();  
  60.            try{  
  61.                page++;  
  62.            }finally{  
  63.                lock.unlock();  
  64.            }             
  65.            String url="http://image.baidu.com/search/avatarjson?tn=resultjsonavatarnew&ie=utf-8&word="+keyword+"&cg=star&pn="+page*30+"&rn=30&itg=0&z=0&fr=&width=&height=&lm=-1&ic=0&s=0&st=-1&gsm="+Integer.toHexString(page*30);  
  66.            String html=null;  
  67.            try {  
  68.             html=getHtml(url);  
  69.             List<String> listUrl=getImgeUrl(html);  
  70.             download(listUrl,downloadPath);  
  71.         } catch (Exception e) {           
  72.             e.printStackTrace();  
  73.         }     
  74.       }  
  75.     }  
  76.     /** 
  77.      * 获取url页面的内容 
  78.      * @param url 
  79.      * @return 
  80.      * @throws Exception 
  81.      */  
  82.     public static String getHtml(String url) throws Exception  
  83.     {  
  84.         URL uri=new URL(url);  
  85.         StringBuffer sb=new StringBuffer();  
  86.         URLConnection connection=uri.openConnection();  
  87.         InputStream in=connection.getInputStream();  
  88.         byte[] buf=new byte[1024];    
  89.         int length=0;  
  90.         while((length=in.read(buf,0,buf.length))>0)  
  91.             sb.append(new String(buf,ENCODE));  
  92.         in.close();       
  93.         return sb.toString();     
  94.     }  
  95.     /** 
  96.      * 获取图片URL 
  97.      * @param html 
  98.      * @return  
  99.      */  
  100.     public static List<String> getImgeUrl(String html)  
  101.     {  
  102.         List<String> listUrl=new ArrayList<String>();  
  103.         String reg = "objURL\":\"http://.+?\\.jpg";  
  104.         Matcher matcher=Pattern.compile(reg).matcher(html);  
  105.         while(matcher.find())  
  106.             listUrl.add(matcher.group().substring(9));  
  107.         return listUrl;  
  108.     }  
  109.     public static void download(List<String> listUrl,String downloadPath)  
  110.     {         
  111.         for(String  url:listUrl)  
  112.         {  
  113.             String imageName=url.substring(url.lastIndexOf("/")+1,url.length());  
  114.             try {  
  115.                 URL uri=new URL(url);  
  116.                 //URLConnection connection=uri.openConnection();  
  117.                 //HttpURLConnection httpCon=(HttpURLConnection)connection;  
  118.                 //InputStream in=httpCon.getInputStream();  
  119.                 InputStream in=uri.openStream();                   
  120.                 String file=downloadPath+imageName;  
  121.                 FileOutputStream fo=new FileOutputStream(new File(file));  
  122.                 byte[] buf=new byte[1024];  
  123.                 int length=0;  
  124.                 while((length=in.read(buf,0,buf.length))!=-1)  
  125.                     fo.write(buf, 0, length);  
  126.                 System.out.println(Thread.currentThread().getName()+url+"下载完成!");  
  127.                 in.close();  
  128.                 fo.close();  
  129.             } catch (FileNotFoundException e1) {                  
  130.                 System.out.println("无法下载图片!");  
  131.             } catch(IOException e2) {  
  132.                 System.out.println("发生IO异常!");  
  133.             }  
  134.         }  
  135.     }  
  136. }  


运行效果:

 

 

 来源:http://blog.csdn.net/gds2014/article/details/51851695

 

posted @ 2017-03-16 13:33  虾米东东  阅读(277)  评论(0编辑  收藏  举报