java從零到變身爬蟲大神

来源:http://www.cnblogs.com/itworkers/archive/2017/09/11/7503689.html
-Advertisement-
Play Games

剛開始先從最簡單的爬蟲邏輯入手 爬蟲最簡單的解析面真的是這樣 這隻是一個函數而已 那麼在下麵加上: 哈哈,搞定 就是這麼一個爬蟲了 太神奇 但是得到的只是網頁的html頁面的東西 而且還沒篩選 那麼就篩選吧 那就用上面的來解析一下我的博客園 解析的是<a>...</a>之間的東西 看起來還不錯吧 我 ...


剛開始先從最簡單的爬蟲邏輯入手

爬蟲最簡單的解析面真的是這樣

import org.jsoup.Jsoup;
import org.jsoup.nodes.Document;
import java.io.IOException;

public class Test {
    public static void Get_Url(String url) {
        try {
         Document doc = Jsoup.connect(url) 
          //.data("query", "Java")
          //.userAgent("頭部")
          //.cookie("auth", "token")
          //.timeout(3000)
          //.post()
          .get();
        } catch (IOException e) {
              e.printStackTrace();
        }
    }
}

這隻是一個函數而已

那麼在下麵加上:

  //main函數
     public static void main(String[] args) {
         String url = "...";
        Get_Url(url);
     }

哈哈,搞定

就是這麼一個爬蟲了

太神奇

但是得到的只是網頁的html頁面的東西

而且還沒篩選

那麼就篩選吧

public static void Get_Url(String url) {
        try {
         Document doc = Jsoup.connect(url) 
          //.data("query", "Java")
          //.userAgent("頭部")
          //.cookie("auth", "token")
          //.timeout(3000)
          //.post()
          .get();
         
        //得到html的所有東西
        Element content = doc.getElementById("content");
        //分離出html下<a>...</a>之間的所有東西
        Elements links = content.getElementsByTag("a");
        //Elements links = doc.select("a[href]");
        // 擴展名為.png的圖片
        Elements pngs = doc.select("img[src$=.png]");
        // class等於masthead的div標簽
        Element masthead = doc.select("div.masthead").first();
            
        for (Element link : links) {
              //得到<a>...</a>裡面的網址
              String linkHref = link.attr("href");
              //得到<a>...</a>裡面的漢字
              String linkText = link.text();
              System.out.println(linkText);
            }
        } catch (IOException e) {
              e.printStackTrace();
        }
    }

那就用上面的來解析一下我的博客園

解析的是<a>...</a>之間的東西

看起來還不錯吧

 

-------------------------------我是一根牛逼的分割線-------------------------------

 

其實還有另外一種爬蟲的方法更加好

他能批量爬取網頁保存到本地

先保存在本地再去正則什麼的篩選自己想要的東西

這樣效率比上面的那個高了很多

看代碼!

//將抓取的網頁變成html文件,保存在本地
    public static void Save_Html(String url) {
        try {
            File dest = new File("src/temp_html/" + "保存的html的名字.html");
            //接收位元組輸入流
            InputStream is;
            //位元組輸出流
            FileOutputStream fos = new FileOutputStream(dest);
    
            URL temp = new URL(url);
            is = temp.openStream();
            
            //為位元組輸入流加緩衝
            BufferedInputStream bis = new BufferedInputStream(is);
            //為位元組輸出流加緩衝
            BufferedOutputStream bos = new BufferedOutputStream(fos);
    
            int length;
    
            byte[] bytes = new byte[1024*20];
            while((length = bis.read(bytes, 0, bytes.length)) != -1){
                fos.write(bytes, 0, length);
            }

            bos.close();
            fos.close();
            bis.close();
            is.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

這個方法直接將html保存在了文件夾src/temp_html/裡面

在批量抓取網頁的時候

都是先抓下來,保存為html或者json

然後在正則什麼的進資料庫

東西在本地了,自己想怎麼搞就怎麼搞

反爬蟲關我什麼事

上面兩個方法都會造成一個問題

這個錯誤代表

這種爬蟲方法太low逼

大部分網頁都禁止了

所以,要加個頭

就是UA

方法一那裡的頭部那裡直接

userAgent("Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.1; Trident/5.0; MALC)")

方法二間接加:

 URL temp = new URL(url);
 URLConnection uc = temp.openConnection();
uc.addRequestProperty("User-Agent", "Mozilla/5.0 (iPad; U; CPU OS 4_3_3 like Mac OS X; en-us) AppleWebKit/533.17.9 (KHTML, like Gecko) Version/5.0.2 Mobile/8J2 Safari/6533.18.5");
  is = temp.openStream();

加了頭部,幾乎可以應付大部分網址了

 

-------------------------------我是一根牛逼的分割線-------------------------------

 

將html下載到本地後需要解析啊

解析啊看這裡啊

//解析本地的html
    public static void Get_Localhtml(String path) {

        //讀取本地html的路徑
        File file = new File(path);
        //生成一個數組用來存儲這些路徑下的文件名
        File[] array = file.listFiles();
        //寫個迴圈讀取這些文件的名字
        
        for(int i=0;i<array.length;i++){
            try{
                if(array[i].isFile()){
                //文件名字
                System.out.println("正在解析網址:" + array[i].getName());

                //下麵開始解析本地的html
                Document doc = Jsoup.parse(array[i], "UTF-8");
                //得到html的所有東西
                Element content = doc.getElementById("content");
                //分離出html下<a>...</a>之間的所有東西
                Elements links = content.getElementsByTag("a");
                //Elements links = doc.select("a[href]");
                // 擴展名為.png的圖片
                Elements pngs = doc.select("img[src$=.png]");
                // class等於masthead的div標簽
                Element masthead = doc.select("div.masthead").first();
                
                for (Element link : links) {
                      //得到<a>...</a>裡面的網址
                      String linkHref = link.attr("href");
                      //得到<a>...</a>裡面的漢字
                      String linkText = link.text();
                      System.out.println(linkText);
                        }
                    }
                }catch (Exception e) {
                    System.out.println("網址:" + array[i].getName() + "解析出錯");
                    e.printStackTrace();
                    continue;
                }
        }
    }

文字配的很漂亮

就這樣解析出來啦

主函數加上

//main函數
    public static void main(String[] args) {
        String url = "http://www.cnblogs.com/TTyb/";
        String path = "src/temp_html/";
        Get_Localhtml(path);
    }

那麼這個文件夾裡面的所有的html都要被我解析掉

好啦

3天java1天爬蟲的結果就是這樣子咯

-------------------------------我是快樂的分割線-------------------------------

 

其實對於這兩種爬取html的方法來說,最好結合在一起

作者測試過

方法二穩定性不足

方法一速度不好

所以自己改正

將方法一放到方法二的catch裡面去

當方法二出現錯誤的時候就會用到方法一

但是當方法一也錯誤的時候就跳過吧

結合如下:

import org.jsoup.Jsoup;
import org.jsoup.nodes.Document;
import org.jsoup.nodes.Element;
import org.jsoup.select.Elements;

import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.net.HttpURLConnection;
import java.net.URL;
import java.net.URLConnection;
import java.util.Date;
import java.text.SimpleDateFormat;

public class JavaSpider {
    
    //將抓取的網頁變成html文件,保存在本地
    public static void Save_Html(String url) {
        try {
            File dest = new File("src/temp_html/" + "我是名字.html");
            //接收位元組輸入流
            InputStream is;
            //位元組輸出流
            FileOutputStream fos = new FileOutputStream(dest);
    
            URL temp = new URL(url);
            URLConnection uc = temp.openConnection();
            uc.addRequestProperty("User-Agent", "Mozilla/5.0 (iPad; U; CPU OS 4_3_3 like Mac OS X; en-us) AppleWebKit/533.17.9 (KHTML, like Gecko) Version/5.0.2 Mobile/8J2 Safari/6533.18.5");
            is = temp.openStream();
            
            //為位元組輸入流加緩衝
            BufferedInputStream bis = new BufferedInputStream(is);
            //為位元組輸出流加緩衝
            BufferedOutputStream bos = new BufferedOutputStream(fos);
    
            int length;
    
            byte[] bytes = new byte[1024*20];
            while((length = bis.read(bytes, 0, bytes.length)) != -1){
                fos.write(bytes, 0, length);
            }

            bos.close();
            fos.close();
            bis.close();
            is.close();
        } catch (IOException e) {
            e.printStackTrace();
            System.out.println("openStream流錯誤,跳轉get流");
            //如果上面的那種方法解析錯誤
            //那麼就用下麵這一種方法解析
            try{
                Document doc = Jsoup.connect(url)
                .userAgent("Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.1; Trident/5.0; MALC)")
                .timeout(3000) 
                .get();
                
                File dest = new File("src/temp_html/" + "我是名字.html");
                if(!dest.exists())
                    dest.createNewFile();
                FileOutputStream out=new FileOutputStream(dest,false);
                out.write(doc.toString().getBytes("utf-8"));
                out.close();

            }catch (IOException E) {
                E.printStackTrace();
                System.out.println("get流錯誤,請檢查網址是否正確");
            }
            
        }
    }
    
    //解析本地的html
    public static void Get_Localhtml(String path) {

        //讀取本地html的路徑
        File file = new File(path);
        //生成一個數組用來存儲這些路徑下的文件名
        File[] array = file.listFiles();
        //寫個迴圈讀取這些文件的名字
        
        for(int i=0;i<array.length;i++){
            try{
                if(array[i].isFile()){
                    //文件名字
                    System.out.println("正在解析網址:" + array[i].getName());
                    //文件地址加文件名字
                    //System.out.println("#####" + array[i]); 
                    //一樣的文件地址加文件名字
                    //System.out.println("*****" + array[i].getPath()); 
                    
                    
                    //下麵開始解析本地的html
                    Document doc = Jsoup.parse(array[i], "UTF-8");
                    //得到html的所有東西
                    Element content = doc.getElementById("content");
                    //分離出html下<a>...</a>之間的所有東西
                    Elements links = content.getElementsByTag("a");
                    //Elements links = doc.select("a[href]");
                    // 擴展名為.png的圖片
                    Elements pngs = doc.select("img[src$=.png]");
                    // class等於masthead的div標簽
                    Element masthead = doc.select("div.masthead").first();
                    
                    for (Element link : links) {
                          //得到<a>...</a>裡面的網址
                          String linkHref = link.attr("href");
                          //得到<a>...</a>裡面的漢字
                          String linkText = link.text();
                          System.out.println(linkText);
                        }
                    }
                }catch (Exception e) {
                    System.out.println("網址:" + array[i].getName() + "解析出錯");
                    e.printStackTrace();
                    continue;
                }
            }
        }
    //main函數
    public static void main(String[] args) {
        String url = "http://www.cnblogs.com/TTyb/";
        String path = "src/temp_html/";
        //保存到本地的網頁地址
        Save_Html(url);
        //解析本地的網頁地址
        Get_Localhtml(path);
    }
}

總的來說

java爬蟲的方法比python的多好多

java的庫真特麽變態


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 設計原則:萬物皆對象 背景:微軟提供了一套強大的通信框架Wcf,瞭解請看百度百科:ttps://baike.baidu.com/item/Wcf/7374854?fr=aladdin 雖然這套通信框架很強大,但是配置起來也不簡單,因此導致很多人望而卻步(包括我),我這人向來不喜歡麻煩,喜歡簡單,最好 ...
  • AOP為Aspect Oriented Programming的縮寫,意為:面向切麵編程,通過預編譯方式和運行期動態代理實現程式功能的中統一處理業務邏輯的一種技術,比較常見的場景是:日誌記錄,錯誤捕獲、性能監控等 AOP的本質是通過代理對象來間接執行真實對象,在代理類中往往會添加裝飾一些額外的業務代 ...
  • 近期逆向一個程式,發現有保護措施,不能載入。用machoview後,發現有__RESTRICT段,因此改為RRSTRICT。 先前用iphone4調試,沒有問題,只是調試過程中老是卡死,要等個半天才能有反應。因此換了iphone5s,9.3.3。安裝後,把修改過的二進位scp到設備,發現閃退了。莫名 ...
  • 因為本人對web機制瞭解較少,在使用C/libcurl中遇到了很多問題。主要的解決方式: 1,在網頁源碼中找到提交form的定位。也就是網頁文件對應form中的action屬性。往往都是提交到jsp或者php等腳本中運行的,而不是直接提交到本網頁。 2,要註意http頭。http頭的不同會引起網頁的 ...
  • C++遠征之封裝篇(上)筆記 所有內容都是聽課筆記,願課堂視頻如下: C++遠征之封裝篇(上)-慕課網http://www.imooc.com/learn/382 類和對象 1 什麼是類,什麼是對象? 對象是具體的事物,而類是出於不同的目的從對象中抽象出來的,所以,同一事物可以抽象成不同的類。 舉個 ...
  • 摘要:ThinkPHP是一個小型網站很常用的低端框架,但是不專業的文檔和編碼導致使用者很容易只知其表不知其里。這裡僅就官方文檔中未曾提及的在thinkphp中使用jquery實現ajax非同步交互略作總結。 環境:ThinkPHP3.2.3,jQuery 閱讀目錄: 正文: 在一般的網站中,都需要用到 ...
  • 這是一個高級Java面試系列題中的第一部分。這一部分論述了可變參數,斷言,垃圾回收,初始化器,令牌化,日期,日曆等等Java核心問題。 1. 什麼是可變參數? 可變參數允許調用參數數量不同的方法。請看下麵例子中的求和方法。此方法可以調用1個int參數,或2個int參數,或多個int參數。 //int ...
  • 1、首先在MyEclipse菜單欄找到"windows"下拉菜單中找到首選項(英文Prefenerces),彈出首選項界面。 2、打開java ——>editor > templates 就出現了templates界面 3、然後點擊右上角的"new",按鈕創建你的組合鍵,在"Name"處輸入你的快捷 ...
一周排行
    -Advertisement-
    Play Games
  • 前言 本文介紹一款使用 C# 與 WPF 開發的音頻播放器,其界面簡潔大方,操作體驗流暢。該播放器支持多種音頻格式(如 MP4、WMA、OGG、FLAC 等),並具備標記、實時歌詞顯示等功能。 另外,還支持換膚及多語言(中英文)切換。核心音頻處理採用 FFmpeg 組件,獲得了廣泛認可,目前 Git ...
  • OAuth2.0授權驗證-gitee授權碼模式 本文主要介紹如何筆者自己是如何使用gitee提供的OAuth2.0協議完成授權驗證並登錄到自己的系統,完整模式如圖 1、創建應用 打開gitee個人中心->第三方應用->創建應用 創建應用後在我的應用界面,查看已創建應用的Client ID和Clien ...
  • 解決了這個問題:《winForm下,fastReport.net 從.net framework 升級到.net5遇到的錯誤“Operation is not supported on this platform.”》 本文內容轉載自:https://www.fcnsoft.com/Home/Sho ...
  • 國內文章 WPF 從裸 Win 32 的 WM_Pointer 消息獲取觸摸點繪製筆跡 https://www.cnblogs.com/lindexi/p/18390983 本文將告訴大家如何在 WPF 裡面,接收裸 Win 32 的 WM_Pointer 消息,從消息裡面獲取觸摸點信息,使用觸摸點 ...
  • 前言 給大家推薦一個專為新零售快消行業打造了一套高效的進銷存管理系統。 系統不僅具備強大的庫存管理功能,還集成了高性能的輕量級 POS 解決方案,確保頁面載入速度極快,提供良好的用戶體驗。 項目介紹 Dorisoy.POS 是一款基於 .NET 7 和 Angular 4 開發的新零售快消進銷存管理 ...
  • ABP CLI常用的代碼分享 一、確保環境配置正確 安裝.NET CLI: ABP CLI是基於.NET Core或.NET 5/6/7等更高版本構建的,因此首先需要在你的開發環境中安裝.NET CLI。這可以通過訪問Microsoft官網下載並安裝相應版本的.NET SDK來實現。 安裝ABP ...
  • 問題 問題是這樣的:第三方的webapi,需要先調用登陸介面獲取Cookie,訪問其它介面時攜帶Cookie信息。 但使用HttpClient類調用登陸介面,返回的Headers中沒有找到Cookie信息。 分析 首先,使用Postman測試該登陸介面,正常返回Cookie信息,說明是HttpCli ...
  • 國內文章 關於.NET在中國為什麼工資低的分析 https://www.cnblogs.com/thinkingmore/p/18406244 .NET在中國開發者的薪資偏低,主要因市場需求、技術棧選擇和企業文化等因素所致。歷史上,.NET曾因微軟的閉源策略發展受限,儘管後來推出了跨平臺的.NET ...
  • 在WPF開發應用中,動畫不僅可以引起用戶的註意與興趣,而且還使軟體更加便於使用。前面幾篇文章講解了畫筆(Brush),形狀(Shape),幾何圖形(Geometry),變換(Transform)等相關內容,今天繼續講解動畫相關內容和知識點,僅供學習分享使用,如有不足之處,還請指正。 ...
  • 什麼是委托? 委托可以說是把一個方法代入另一個方法執行,相當於指向函數的指針;事件就相當於保存委托的數組; 1.實例化委托的方式: 方式1:通過new創建實例: public delegate void ShowDelegate(); 或者 public delegate string ShowDe ...