爬蟲(一):基本內容回顧
本人最近在學習爬蟲的相關知識,對於很多基本的概念在此做一個梳理,便於課程的複習和鞏固,如有寫的不準確或錯誤的地方,歡迎閱讀者批評指正。
要聊爬蟲主要是從以下幾個方面為主線:
- 什麼是爬蟲?
- 爬蟲的價值
- 爬蟲的分類
- 爬蟲的基本執行原理
- 爬蟲的三大模組
- 爬蟲協議
1.什麼是爬蟲?
想到爬蟲,很多人的第一印象就是現實世界中到處爬著找食物的蟲子,其實在計算機的世界裡亦是如此:所謂的爬蟲就是程式設計師寫好的一段程式程式碼,而它們想要找的食物就是存在於網際網路上的形形色色的各種資料,但是有一點需要注意的是這些爬蟲都是按照它們的締造者的意圖即一定的規則自動爬取資料,然後儲存起來加以利用。
2.爬蟲的價值
爬蟲的價值其實就是資料的價值,在萬物互聯的網際網路社會資料是無價之寶,一切皆為資料,誰擁有了大量有用的資料,誰就擁有了決策的主動權,試想如果電商公司擁有了大量的資料,就可以根據年齡段等做精準的廣告推薦,同時還可以做競品分析等等。
3.爬蟲的分類
3.1 通用型的爬蟲
通用型爬蟲是用來獲取網際網路當中所有的資料的, 代表性巨無霸爬蟲: 百度,谷歌,必應(不知道算不?)等 。
3.2 垂直爬蟲
垂直爬蟲,有的資料上也稱之為聚焦爬蟲,主要用來獲取某個行業, 某個分類, 某個網站下的某些資料,具有明顯的針對性和目的性。在我們實際開發過程中, 大部分同學可能接觸到的是垂直爬蟲, 做資料的區域性爬取,而通用型爬蟲的研發和成本太高,一般中小型公司不會輕易去做。
4.爬蟲的基本執行原理
爬蟲的基本執行原理共分為四步:
1)首先指定爬蟲要獲取的url;
2)然後根據對應的url去網上爬取對應的資料;
3)初始爬取到的資料多為html或json格式的,故需要進行資料的解析;
4)解析後的資料即是整理好的資料,儲存到容器中(MySQL,原生JDBC,MyBatis,DbcpUtils,Spring-jdbc等)。
5.爬蟲的三大模組
根據爬蟲的基本執行原理不難得到爬蟲的三大模組:獲取資料,解析資料,儲存資料。
5.1 模組一:獲取資料
獲取資料可以使用原生的JDK(GET/POST),但是這樣做既費時又費力,因此我們選擇使用Apache提供的專為http請求而生的httpClient工具。
使用httpClient之前需要導包:
<dependency>
<groupId>org.apache.httpcomponents</groupId>
<artifactId>httpclient</artifactId>
<version>版本號自定義</version>
</dependency>
具體的程式碼邏輯實現在這裡不過多體現,僅把核心的幾個步驟羅列出來供理清思路:
- 第一步:指定需要獲取的url
- 第二步:建立httpClient物件,指定請求的方式(GET/POST)
- 第三步:傳送http請求
- 第四步:獲取伺服器響應的狀態碼(判斷是否請求成功)
- 第五步:獲取響應體中需要的資料並儲存
- 第六步:關閉httpClient(釋放資源)
注:對於httpClient的post請求,我們還可以在傳送請求之前封裝一些自定義的內容,但是據我的測試後發現,似乎並沒有什麼卵用,也可能是我沒有GET到這個封裝引數的意義何在。
5.2 模組二:解析資料
解析資料是爬蟲很重要的一個環節,因為獲取到的資料(大多數情況下)可能並不是直接整理好的我們需要的格式或部分,因此就很有必要進行解析資料,將獲取到的資料歸納整理出我們需要的部分和格式。
解析資料需要使用到的也是Apache提供的名叫Jsoup的工具,專門用來進行網頁資料的解析。同樣的,在使用Jsoup之情也需要導包:
<dependency>
<groupId>org.jsoup</groupId>
<artifactId>jsoup</artifactId>
<version>版本自定義</version>
</dependency>
Jsoup當中提供了兩套API供程式設計師使用:
第一套: 採用原生DOM解析的方案獲取網頁中的資料
@Test
public void indexparse() throws IOException {
// 1.獲取document物件
Document document = Jsoup.connect("url").get();
// 2.解析網頁
// 2.1 獲取當前網頁的標題內容
String title = document.title();
System.out.println(title);
// 2.2 通過id獲取內容
Element element = document.getElementById("epContentLeft");
// 2.3 通過元素標籤獲取內容
Elements h1Elements = element.getElementsByTag("h1");
System.out.println(h1Elements.size());
Element element1 = h1Elements.get(0);
String text = element1.text();
System.out.println(text);
}
第二套: 採用是類似CSS的選擇器的方案獲取網頁的資料
首先要清楚常用的選擇器種類,在這裡我僅列舉出來幾個有代表性的供參考:
- id選擇器:(#)
- 類選擇器:(.)
- 標籤選擇器(標籤名稱)
- 層級選擇器(空格 > + , )
- 屬性選擇器([屬性名=屬性值])
關於選擇器還有很多好用的,由於時間關係,不在此展示,但是在實際的工作當中,要多參考,多嘗試不同的選擇器,也許會有意想不到的結果。
@Test
public void indexSelectParse() throws IOException {
// 1.獲取document物件
Document document = Jsoup.connect("url").get();
// 2.獲取網頁的標題
Elements elements = document.select("title");
//System.out.println(elements.get(0).text());
System.out.println(elements.text());
// 3.獲取內容的標題
// 注:選擇器的寫法, 一定要按照規範來
Elements htEl = document.select("#epContentLeft h1");
System.out.println(htEl.text());
}
5.3 模組三:儲存資料
對於開篇提到的五種(應該還不止)儲存資料的方式,根據實際的應用和需求。
需要注意的是:資料庫連線池的配置切不可粗心大意,否則會無法正常存入資料,以下是我練習過的一個簡單的網頁爬蟲的案例用到了上述所講的知識點,留在這裡供以後複習:
public class Spider {
/**
* 需求:*****
*/
public static void main(String[] args) throws IOException {
// 1.指定url
String urlStr = "url";
// 2.獲取httpClient物件
CloseableHttpClient httpClient = HttpClients.createDefault();
// 3.指定請求方式(get)
HttpGet httpGet = new HttpGet(urlStr);
// 4.執行請求, 獲取響應物件
CloseableHttpResponse response = httpClient.execute(httpGet);
// 5.獲取HTML頁面(獲取資料)
String html = EntityUtils.toString(response.getEntity(), "utf-8");
// 6.使用jsoup解析網頁
// 6.1 獲取document物件
Document document = Jsoup.parse(html);
// 6.2 解析document
Elements elements = document.select("div[class=*]");
Elements lis = elements.select("*");
Elements as = lis.select("a[href*=*****.com]");
as = as.select("[class]");
for (Element a : as) {
String bookUrl = a.attr("href");
// 拼接url
bookUrl = "https:" + bookUrl;
httpClient = HttpClients.createDefault();
httpGet = new HttpGet(bookUrl);
response = httpClient.execute(httpGet);
html = EntityUtils.toString(response.getEntity(), "UTF-8");
document = Jsoup.parse(html);
Elements aBtn = document.select("*");
bookUrl = aBtn.attr("href");
while (true) {
// 拼接新的url
bookUrl = "https:" + bookUrl;
System.out.println(bookUrl);
httpClient = HttpClients.createDefault();
httpGet = new HttpGet(bookUrl);
response = httpClient.execute(httpGet);
html = EntityUtils.toString(response.getEntity(), "UTF-8");
document = Jsoup.parse(html);
// 開始解析內容
Elements title = document.select("*");
// ***的名稱
System.out.println(title.text());
// ***的內容
Elements ps = document.select("div[*");
for (Element p : ps) {
System.out.println(p.text());
}
Elements aEl = document.select("#j_chapterNext[href*=*****.com]");
// 判斷是否繼續爬取
if (aEl.size() == 0) {
System.out.println("爬取完畢,結束");
break;
}
bookUrl = aEl.attr("href");
}
}
}
}
6.爬蟲協議
事物本沒有對與錯之分,所謂的對與錯不過是每個人心中不同的準繩。爬蟲作為一種技術,更像是一把雙刃劍,如果利用得當,會給社會創造更大的價值,惠及四方;但若被別有用心的人加以利用,則可能會遭到社會道德的抵制和譴責。因此才有了公認的爬蟲原則:
1、搜尋技術應服務於人類,同時尊重資訊提供者的意願,並維護其隱私權;
2、網站有義務保護其使用者的個人資訊和隱私不被侵犯。
robots協議:百度百科
爬蟲協議,也稱為Robots協議,其本身是一個文字檔案,當爬蟲在網際網路上爬取資料時首先要訪問的就是這個檔案,具體的檢視方式(以百度為例):https://www.baidu.com/robots.txt,即可看到該網站的爬蟲宣告,裡面的內容主要是宣告本網站是否希望被爬蟲爬取以及哪些內容可以/不可以被爬取。