JAVA爬取亞馬遜的商品信息


在程序里面輸入你想爬取的商品名字,就可以返回這件商品在亞馬遜搜索中都所有相關商品的信息,包括名字和價格。

解決了在爬取亞馬遜時候,亞馬遜可以識別出你的爬蟲,並返回503,造成只能爬取幾個頁面的問題。

除此之外亞馬遜網頁代碼寫得非常的亂啊(可能是我個人問題?),要想提取里面的信息非常麻煩。

純JAVA編寫,用的都是java自帶的庫。

先展示一下效果圖:

商品頁面:

 

爬取的信息頁面(消除重復了):

 

名字和價格是絕對正確的,例如上圖31行的商品:

 

主要思路是這樣的:

1、打開搜索的列表頁,然后抽取所有商品頁的url和下一頁的url,加入爬取的隊列。

2、判斷若是列表頁則重復步驟1,若是商品詳細信息的頁面,提取商品名稱和價格到一個文件中。

 

遇到的主要問題:

1、亞馬遜的頁面限制流量,如果在限定的時間內訪問次數太多,就會返回503。一般是爬取幾張頁面后就不能繼續下去了。如圖:

 

解決辦法是:

a、盡量模仿瀏覽器,辦法就是設置User-Agent啦!用一個數組存了 多個User-Agent,然后隨機調用。

b、降速,適當延長兩次請求的時間。

c、去重,重復的url

d、掛代理,這個就算了,太復雜

 

 

2、亞馬遜的代碼很亂!提取有用的信息十分困難。不過細心找還是能發現規律的,我用正則表達式來提取的。

亞馬遜搜索頁面的url(就是搜索商品后回車的頁面):

"http://www.amazon.cn/s/ref=nb_sb_noss?__mk_zh_CN=%E4%BA%9A%E9%A9%AC%E9%80%8A%E7%BD%91%E7%AB%99&field-keywords="+商品名;

對於商品頁面的抽取,商品名字和價格的抽取等等在代碼里面。

 

3、在列表里面會有同一件商品的3~4個url名字,可以跳轉到名字部分,圖文信息部分還有評論部分的。

要判斷如果這些頁面的商品編號相同,就只取一個就好了。例如:

http://www.amazon.cn/%E6%89%8B%E6%9C%BA-%E9%80%9A%E8%AE%AF/dp/B00OB5T26S......

dp后面是商品編號。

 

代碼只爬取了搜索頁的第一頁,因為第一頁的商品最貼近我們想要的東西,而且后面的頁面很多都是重復的或者是不相關的了。

除了我們搜索一個品牌才會有很多頁,一般搜索具體的東西還是第一頁比較靠譜。當然,也可以爬取后面的頁面啦,url在html中,自己提取就行。

 

public class amazon {
    
    public static int i=0;
    
    //用來儲存上一個商品編號,看有沒有重復
    public static String last = "|";

    
    //匹配商品url
    public static Pattern p_goods = Pattern.compile("href=\"(http://www(.+?)/dp/(.+?))\"");
    
    
    //存放待爬取的url
    public static Queue<String> data = new LinkedList<String>();
    
    //要輸入到file中
    public static File file;
    
    //15個ua隨機用,減少503的機率
    public static String [] ua = {
            "Mozilla/5.0 (Windows NT 6.1; rv:2.0.1) Gecko/20100101 Firefox/4.0.1",
            "Mozilla/5.0 (Windows NT 6.1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/31.0.1650.16 Safari/537.36",
            "Mozilla/5.0 (Windows NT 6.1; Intel Mac OS X 10.6; rv:7.0.1) Gecko/20100101 Firefox/7.0.1",
            "Mozilla/5.0 (Windows NT 6.1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/31.0.1650.63 Safari/537.36 OPR/18.0.1284.68",
            "Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 6.0; Trident/4.0)",
            "Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.1; Trident/5.0)",
            "Mozilla/5.0 (compatible; MSIE 10.0; Windows NT 6.2; Trident/6.0)",
            "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_9_1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/31.0.1650.63 Safari/537.36",
            "Mozilla/5.0 (Macintosh; Intel Mac OS X 10.6; rv:2.0.1) Gecko/20100101 Firefox/4.0.1",
            "Mozilla/5.0 (Macintosh; Intel Mac OS X 10.6; rv:7.0.1) Gecko/20100101 Firefox/7.0.1",
            "Opera/9.80 (Macintosh; Intel Mac OS X 10.9.1) Presto/2.12.388 Version/12.16",
            "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_9_1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/31.0.1650.63 Safari/537.36 OPR/18.0.1284.68",
            "Mozilla/5.0 (iPad; CPU OS 7_0 like Mac OS X) AppleWebKit/537.51.1 (KHTML, like Gecko) CriOS/30.0.1599.12 Mobile/11A465 Safari/8536.25",
            "Mozilla/5.0 (iPad; CPU OS 8_0 like Mac OS X) AppleWebKit/600.1.3 (KHTML, like Gecko) Version/8.0 Mobile/12A4345d Safari/600.1.4",
            "Mozilla/5.0 (iPad; CPU OS 7_0_2 like Mac OS X) AppleWebKit/537.51.1 (KHTML, like Gecko) Version/7.0 Mobile/11A501 Safari/9537.53"
            
    };
    
    
    
    public static void action(String target) throws IOException, InterruptedException{
        
        
        //補全targer的搜索頁面
        if(i==0){
            
            target = "http://www.amazon.cn/s/ref=nb_sb_noss?__mk_zh_CN=%E4%BA%9A%E9%A9%AC%E9%80%8A%E7%BD%91%E7%AB%99&field-keywords="+target;
            i++;
            
        }
        
        //先打開輸入流
        URL url = new URL(target);
        
        HttpURLConnection conn = (HttpURLConnection)url.openConnection();
        
        conn.setRequestMethod("GET");
        
        
        Random index = new Random();
        
        String u = ua[Math.abs(index.nextInt()%15)];
        //System.out.println("us--->"+u);
        //隨機調用ua
        conn.setRequestProperty("User-Agent",u);
        
        conn.setRequestProperty("Host","www.amazon.cn");
        conn.setRequestProperty("Accept","text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8");
        conn.setRequestProperty("Connection","keep-alive");
        
        conn.connect();
        
        InputStream in = conn.getInputStream();
        
        byte [] buf = new byte[1024];
        
        //把數據裝進ByteArrayOutputStream中
         ByteArrayOutputStream outStream = new ByteArrayOutputStream();
     
         int len = 0;
        
        while((len=in.read(buf))!=-1){
            
            outStream.write(buf,0,len);
        }
        in.close();
        outStream.close();
        
        String content = new String(outStream.toByteArray());
        
        
        //判斷頁面類型
        
        Pattern pp_goods = Pattern.compile("http://www(.+?)/dp/(.+)");
        Matcher m_goods = pp_goods.matcher(target);
        
        
        //如果是商品頁面
        if(m_goods.find()){
            
            System.out.println("This is goods page");
            
            //提取名字和價格
            Pattern p_name = Pattern.compile("<meta name=\"description\" content=\"(.+?),");
  
            Matcher m_name = p_name.matcher(content);
            
            Pattern p_price = Pattern.compile("class=\"a-size-medium a-color-price\">¥(.+?)</span>");

            Matcher m_price = p_price.matcher(content);
            
            
            //文件寫操作
            PrintWriter pw = new PrintWriter(new FileWriter("goods.txt", true));
            
            
            while(m_name.find()){
                
                
                pw.print(m_name.group(1)+"------->");
                
            }
            while(m_price.find()){
                
                
                pw.println(m_price.group(1));
                
            }
            
           pw.close();
            
           
       
            
        }
        //其他就是列表頁面了
        else{
            
            
            
            //提取里面的商品url
            
                m_goods = p_goods.matcher(content);
            
                int count = 0;
                
                //提取這個url的編號
                Pattern p_num = Pattern.compile("/dp/(.+?)/");
                
                
                while(m_goods.find()){
                
                
                    
                    String current = m_goods.group(1);
                    
                    
                    
                    Matcher m_num = p_num.matcher(current);
                    
                    String current_num = "";
                    
                    if(m_num.find()){
                        current_num = m_num.group(1);
                        //System.out.println(current_num);
                    }
                    
                    
                
                    //去重!!!!!!!!!
                        
                    //如果不等於上一個商品編號,才將該url加入隊列
                    if(!current_num.equals(last)){
                        //System.out.println(current);
                        //System.out.println(current_num);
                        //System.out.println("goods url");
                        data.add(current);
                        last = current_num;    
                    
                    }
                
                }
                
                
                
                
                }
                
                
            
            
            
            
        }
        
        
    
        
        
    
    
    
    
    public static void main(String args[]) throws IOException, InterruptedException{
        
        
        //直接輸入商品名字就好了
        String target = "macbook pro";
        
        amazon.action(target);
        
        
        
        //如果隊列非空,則一直進行
        while(!data.isEmpty()){  
            
            
            
            amazon.action(data.poll());
            
            
            
        }
            
    }
    
        
        
        
    }

 

效果:

才第一頁就已經比較多無用的東西了,比如保護膜什么什么的。我一開始是爬取了很多頁面的,但發現后面都是一些沒用的東西,所以后面的頁面意義不大。

 

其實真正高效的話,還是要用到多線程和一些去重技術,這里只是一個簡單的實例。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM