1. 程式人生 > 實用技巧 >Java 網路爬蟲新手入門詳解

Java 網路爬蟲新手入門詳解

這是 Java 網路爬蟲系列文章的第一篇,如果你還不知道 Java 網路爬蟲系列文章,請參看Java 網路爬蟲基礎知識入門解析。第一篇是關於 Java 網路爬蟲入門內容,在該篇中我們以採集虎撲列表新聞的新聞標題和詳情頁為例,需要提取的內容如下圖所示:

我們需要提取圖中圈出來的文字及其對應的連結,在提取的過程中,我們會使用兩種方式來提取,一種是 Jsoup 的方式,另一種是 httpclient + 正則表示式的方式,這也是 Java 網路爬蟲常用的兩種方式,你不瞭解這兩種方式沒關係,後面會有相應的使用手冊。在正式編寫提取程式之前,我先交代一下 Java 爬蟲系列博文的環境,該系列博文所有的 demo 都是使用 SpringBoot 搭建的,不管你使用哪種環境,只需要正確的匯入相應的包即可。

Jsoup 方式提取資訊

我們先來使用 Jsoup 的方式提取新聞資訊,如果你還不知道 Jsoup ,請參考https://jsoup.org/

先建立一個 Springboot 專案,名字就隨意啦,在 pom.xml 中引入 Jsoup 的依賴

<dependency>
 <groupId>org.jsoup</groupId>
 <artifactId>jsoup</artifactId>
 <version>1.12.1</version>
</dependency>

好了,接下來我們一起分析頁面吧,想必你還沒瀏覽過吧,點選這裡瀏覽

虎撲新聞。在列表頁中,我們利用 F12 審查元素檢視頁面結構,經過我們分析發現列表新聞在 <div class="news-list">標籤下,每一條新聞都是一個li標籤,分析結果如下圖所示:

由於我們前面已經知道了 css 選擇器,我們結合瀏覽器的 Copy 功能,編寫出我們 a標籤的 css 選擇器程式碼:div.news-list > ul > li > div.list-hd > h4 > a ,一切都準備好了,我們一起來編寫 Jsoup 方式提取資訊的程式碼:

/**
 * jsoup方式 獲取虎撲新聞列表頁
 * @param url 虎撲新聞列表頁url
 */
public void jsoupList(String url){
 try {
  Document document = Jsoup.connect(url).get();
  // 使用 css選擇器 提取列表新聞 a 標籤
  // <a href="https://voice.hupu.com/nba/2484553.html" rel="external nofollow" target="_blank">霍華德:夏休期內曾節食30天,這考驗了我的身心</a>
  Elements elements = document.select("div.news-list > ul > li > div.list-hd > h4 > a");
  for (Element element:elements){
//    System.out.println(element);
   // 獲取詳情頁連結
   String d_url = element.attr("href");
   // 獲取標題
   String title = element.ownText();

   System.out.println("詳情頁連結:"+d_url+" ,詳情頁標題:"+title);

  }
 } catch (IOException e) {
  e.printStackTrace();
 }
}

使用 Jsoup 方式提取還是非常簡單的,就5、6行程式碼就完成了,關於更多 Jsoup 如何提取節點資訊的方法可以參考 jsoup 的官網教程。我們編寫 main 方法,來執行 jsoupList 方法,看看 jsoupList 方法是否正確。

public static void main(String[] args) {
 String url = "https://voice.hupu.com/nba";
 CrawlerBase crawlerBase = new CrawlerBase();
 crawlerBase.jsoupList(url);
}

執行 main 方法,得到如下結果:

從結果中可以看出,我們已經正確的提取到了我們想要的資訊,如果你想採集詳情頁的資訊,只需要編寫一個採集詳情頁的方法,在方法中提取詳情頁相應的節點資訊,然後將列表頁提取的連結傳入提取詳情頁方法即可。

httpclient + 正則表示式

上面我們使用了 Jsoup 方式正確提取了虎撲列表新聞,接下來我們使用 httpclient + 正則表示式的方式來提取,看看使用這種方式又會涉及到哪些問題?httpclient + 正則表示式的方式涉及的知識點還是蠻多的,它涉及到了正則表示式、Java 正則表示式、httpclient。如果你還不知道這些知識,可以點選下方連結簡單瞭解一下:

正則表示式:正則表示式

Java 正則表示式:Java 正則表示式

httpclient:httpclient

我們在 pom.xml 檔案中,引入 httpclient 相關 Jar 包

<dependency>
 <groupId>org.apache.httpcomponents</groupId>
 <artifactId>httpclient</artifactId>
 <version>4.5.10</version>
</dependency>
<dependency>
 <groupId>org.apache.httpcomponents</groupId>
 <artifactId>httpcore</artifactId>
 <version>4.4.10</version>
</dependency>
<dependency>
 <groupId>org.apache.httpcomponents</groupId>
 <artifactId>httpmime</artifactId>
 <version>4.5.10</version>
</dependency>

關於虎撲列表新聞頁面,我們在使用 Jsoup 方式的時候進行了簡單的分析,這裡我們就不在重複分析了。對於使用正則表示式方式提取,我們需要找到能夠代表列表新聞的結構體,比如: <div class="list-hd"> <h4> <a href="https://voice.hupu.com/nba/2485508.html" rel="external nofollow" target="_blank">直上雲霄!魔術官方社媒晒富爾茨扣籃炫酷特效圖</a></h4></div>

這段結構體,每個列表新聞只有連結和標題不一樣,其他的都一樣,而且 <div class="list-hd">是列表新聞特有的。最好不要直接正則匹配 a標籤,因為 a標籤在其他地方也有,這樣我們就還需要做其他的處理,增加我們的難度。現在我們瞭解了正則結構體的選擇,我們一起來看看 httpclient + 正則表示式方式提取的程式碼:

/**
 * httpclient + 正則表示式 獲取虎撲新聞列表頁
 * @param url 虎撲新聞列表頁url
 */
public void httpClientList(String url){
 try {
  CloseableHttpClient httpclient = HttpClients.createDefault();
  HttpGet httpGet = new HttpGet(url);
  CloseableHttpResponse response = httpclient.execute(httpGet);
  if (response.getStatusLine().getStatusCode() == 200) {
   HttpEntity entity = response.getEntity();
   String body = EntityUtils.toString(entity,"utf-8");
 
   if (body!=null) {
     /*
     * 替換掉換行符、製表符、回車符,去掉這些符號,正則表示寫起來更簡單一些
     * 只有空格符號和其他正常字型
     */
    Pattern p = Pattern.compile("\t|\r|\n");
    Matcher m = p.matcher(body);
    body = m.replaceAll("");
    /*
     * 提取列表頁的正則表示式
     * 去除換行符之後的 li
     * <div class="list-hd">         <h4>          <a href="https://voice.hupu.com/nba/2485167.html" rel="external nofollow" target="_blank">與球迷親切互動!凱爾特人官方晒球隊開放訓練日照片</a>         </h4>        </div>
     */
    Pattern pattern = Pattern
      .compile("<div class=\"list-hd\">\\s* <h4>\\s* <a href=\"(.*?)\"\\s* target=\"_blank\">(.*?)</a>\\s* </h4>\\s* </div>" );

    Matcher matcher = pattern.matcher(body);
    // 匹配出所有符合正則表示式的資料
    while (matcher.find()){
//      String info = matcher.group(0);
//      System.out.println(info);
     // 提取出連結和標題
     System.out.println("詳情頁連結:"+matcher.group(1)+" ,詳情頁標題:"+matcher.group(2));
    }
   }else {
    System.out.println("處理失敗!!!獲取正文內容為空");
   }
  } else {
   System.out.println("處理失敗!!!返回狀態碼:" + response.getStatusLine().getStatusCode());
  }
 }catch (Exception e){
  e.printStackTrace();
 }

}

從程式碼的行數可以看出,比 Jsoup 方式要多不少,程式碼雖然多,但是整體來說比較簡單,在上面方法中我做了一段特殊處理,我先替換了 httpclient 獲取的字串 body 中的換行符、製表符、回車符,因為這樣處理,在編寫正則表示式的時候能夠減少一些額外的干擾。接下來我們修改 main 方法,執行 httpClientList 方法。

public static void main(String[] args) {
 String url = "https://voice.hupu.com/nba";
 CrawlerBase crawlerBase = new CrawlerBase();
//  crawlerBase.jsoupList(url);
 crawlerBase.httpClientList(url);
}

執行結果如下圖所示:

使用 httpclient + 正則表示式的方式同樣正確的獲取到了列表新聞的標題和詳情頁連結。到此 Java 爬蟲系列博文第一篇就寫完了,這一篇主要是 Java 網路爬蟲的入門,我們使用了 jsoup 和 httpclient + 正則的方式提取了虎撲列表新聞的新聞標題和詳情頁連結。當然這裡還有很多沒有完成,比如採集詳情頁資訊存入資料庫等。

原始碼:點選這裡

以上就是本文的全部內容,希望對大家的學習有所幫助,也希望大家多多支援碼農教程。