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
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...