使用jsoup十分鍾內掌握爬蟲技術


  對,就是十分鍾,沒有接觸過爬蟲的你,肯定一臉懵逼,感覺好高深的樣子,一開始我也有點懵,但用了以后發現還是很簡單的,java爬蟲框架有很多,讓我有種選擇困難症,通過權衡比較還是感覺jsoup比較好用些,簡單強大,怎么簡單強大呢?看了后面你就知道了。

  為什么要給大家講一下使用jsoup呢?一是為了大家少走彎路,能快速掌握爬蟲技術,不要像我一樣繞了幾個小時在這上面。二是如果我講的不好或是哪里有不對的地方麻煩大家在評論區指出來,大家一起討論討論,就像我們公司的口號一樣,幫助他人就是成就我自己。記得剛入行的時候,所在的公司是做旅游方向軟件的,主要工作是開發各縣區的旅游景區APP,每做一個app我就要上網找數據,錄數據,作為現場競標演示使用。那時候也蠢,只知道上網找數據,然后復制粘貼,一個景區的數據少則一天,多則一個禮拜。在這家公司工作的一年時間里,差不多有三四個月是在無腦錄數據,而不是專研在技術上,現在想想就心痛,如果當時用爬蟲的話,就可以省下一大筆時間了,多的時間用在技術和泡妞上不知道有多nice。所以大家應該知道掌握爬蟲的重要性了吧!

  大家是不是有點不耐煩了,在罵我還不進入正題,好好好,現在進入正題,我們以需求的方式去講這次的內容吧!我的需求是這樣的:爬取某網站的深圳寫字樓數據,保存到我們自己的數據庫,以充實我們的數據量。我們就拿點點租為例吧!首先我們進入點點租官網(http://sz.diandianzu.com/listing),如圖所示:

 

   怎么才能通過jsoup爬取到所有寫字樓數據呢?先劇透一點,通過Document doc = Jsoup.connect(“http://sz.diandianzu.com/listing”).get()就能獲取當前頁http://sz.diandianzu.com/listing的html源碼,所以我們是通過源碼標簽,id選擇器,類選擇器等多種方式去找到我們所要的數據。作為一個java程序員,如果你對html一概不知的話,我真想認識認識你,這是程序員必備技能。首先我們通過偽代碼的方式去實現它!爬取數據最主要的一點就是找網站規律,實現代碼很簡單。我們可以先花三十秒思考一下怎么才能爬取到所有深圳寫字樓的數據呢?

  1.我們要獲取到當前頁的所有樓盤id 2. 我們要獲取到所有頁的樓盤id 3. 通過樓盤id獲取樓盤詳情。你是不是也是這么想的呢?首先我們通過f12查看一下源代碼,查找一下當前頁的樓盤id,如圖所示,我們可以很快查找到當前頁所有樓盤的id,如圖所示:

 

  現在我們只是找到了當前頁的所有樓盤id,怎么才能獲取到所有頁的樓盤id呢?我們先看一下第二頁,如圖所示:

 

  注意看網址:http://sz.diandianzu.com/listing/p2/,你翻到第三頁就是http://sz.diandianzu.com/listing/p3/,以此類推,我們知道只需要改變p后面的數值就能獲取到第N的數據啦,這在代碼實現上很簡單,我們只要在一個循環就能讀取到所有頁的數據了,怎么才知道當前頁是最后一頁數據呢?我們可以通過比較一下有數據和沒有數據的頁面源碼區別就知道了,代碼部分后面講。獲取所有頁的id規律我們知道了,怎么通過id獲取當詳情數據呢?我們隨便點開一個樓盤的詳情頁,如圖所示,還是重點看url部分:

  

  看到http://sz.diandianzu.com/listing/detail-i179.html這個url,我們再隨便打開一下另外一個項目詳情的url:http://sz.diandianzu.com/listing/detail-i3484.html,發現他們的區別只是i后面的數值不一樣,這個179和3484是什么呢?你肯定想的到就是我們的樓盤id啦,所以通過循環樓盤id列表,然后循環解析http://sz.diandianzu.com/listing/detail-i{樓盤id}.html的方式就能獲取到所有樓盤詳情啦!

  規律是找到了,現在我們開始簡單的代碼過程吧!在碼代碼之前,我們可以先看看jsoup的中文文檔:http://www.open-open.com/jsoup/dom-navigation.htm,只需要根據文檔就能輕易獲取到當前頁任意一段代碼內容。首先我們從一個URL加載一個Document,如圖所示:

 

  我的代碼也是這樣的,直接在main方法中運行。別忘了先把jsoup 的jar包引入進來:

  Document doc = Jsoup.connect("http://sz.diandianzu.com/listing").get();

  debug以下查看doc輸出內容拷貝到文本編輯器我們可看到就是當前頁的html源代碼,我們先找到樓盤列表這一塊的div源代碼,如圖所示:

我們的樓盤數據都在class為list-main里面呢,根據jsoup文檔我們通過查找元素方法:getElementsByClass(String className)定位到list-main這個div里面去,再根據使用選擇器語法來查找元素Element.select(String selector) 遍歷div里面的data-id就能獲取到所有的樓盤id了,代碼如圖所示:

只需要根據jsoup文檔就能很快獲取到我們想要的元素值。怎么獲取所有頁面的寫字樓id呢?我們改造一下這段代碼,如圖所示:

  是不是很簡單呢?但這里還有一個問題,是怎么判斷是不是最后一頁,是最后一頁我們就得跳出循環,不然會一直查找下去,導致程序停止不了,我們查找一下沒有數據的list-main跟有數據的list-main里面的源代碼區別,在url輸入http://sz.diandianzu.com/listing/p2000/ 看到沒有樓盤數據了,如圖所示:

  好,我們解析一下這個頁面的html源碼,看一下它的代碼是怎么樣的?解析出來后如圖所示:

看到沒有,list-main類選擇這個div里面沒有任何東西,所以我們只需要判斷data-id這個標簽值存不存在,就可以知道是不是最后一頁,不存在值就直接退出,完整獲取所有樓盤id的代碼:

package com.zhaoshang800.boot;

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

import java.io.IOException;
import java.util.ArrayList;
import java.util.List;

/**
* @author zhx
* @create 2018-10-27 18:32
* @desc 爬蟲測試
**/
public class ReptileTest {

public static void main(String[] args) throws IOException {

try {
long startTime = System.currentTimeMillis();
List<String> buildingIdList = new ArrayList<>();
int pageNum = 0;
while (1 == 1) {
pageNum++;
try {
System.out.println("當前頁:" + pageNum);
String url = "http://sz.diandianzu.com/listing/p"+pageNum;
Document doc = Jsoup.connect(url).get();
if(doc == null){
continue;
}
Elements data = doc.getElementsByClass("list-main");
Elements dataIdList = data.select("[data-id]");
if (null == dataIdList || dataIdList.size() <= 0) {
break;
}
for (Element dataIdElement : dataIdList) {
String dataId = dataIdElement.attr("data-id");
System.out.println("寫字樓id:" + dataId);
buildingIdList.add(dataId);
}
} catch (Exception e) {
e.printStackTrace();
}
}
System.out.println("一共有寫字樓"+buildingIdList.size());
long endTime = System.currentTimeMillis();
System.out.println("獲取樓盤id一共用時"+(endTime - startTime)/1000+"秒");
} catch (Exception e) {
e.printStackTrace();
}
}

  把我這段代碼復制過去直接運行main方法就可以打印出所有的樓盤id了,如圖所示:


  是不是很簡單,后面的獲取所有樓盤詳情想必大家應該知道怎么做了吧?留給大家自己動手去做吧,如果還有疑問的或是有什么指教的話,可以在評論區聯系我,我會第一時間一一答復。


免責聲明!

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



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